




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第SpringBoot示例分析講解自動(dòng)化裝配機(jī)制核心注解目錄1.自動(dòng)化裝配介紹2.SpringBoot自動(dòng)化配置UML圖解3.SpringBoot自動(dòng)化配置核心注解分析3.1@Inherited3.2@SpringBootConfiguration3.3@EnableAutoConfiguration3.4@ComponentScan3.5@ConfigurationPropertiesScan3.6@AutoConfigurationImportSelector3.7@AutoConfigurationPackages4.總結(jié)
1.自動(dòng)化裝配介紹
SpringBoot針對(duì)mvc做了大量封裝,簡(jiǎn)化開(kāi)發(fā)者的使用,內(nèi)部是如何管理資源配置,Bean配置,環(huán)境變量配置以及啟動(dòng)配置等?實(shí)質(zhì)是SpringBoot做了大量的注解封裝,比如@SpringBootApplication,同時(shí)采用Spring4框架的新特性@Conditional基于條件的Bean創(chuàng)建管理機(jī)制來(lái)實(shí)現(xiàn);
實(shí)際的工作場(chǎng)景中是復(fù)雜多樣的,有些項(xiàng)目需要不同的組件,比如REDIS、MONGODB作緩存;RABBITMQ、KAFKA作消息隊(duì)列;有些項(xiàng)目運(yùn)行環(huán)境不同,比如JDK7、JDK8不同版本,面對(duì)眾多復(fù)雜的需求,又要做到最大化支持,SpringBoot是如何管理實(shí)現(xiàn)的,這就依賴(lài)Conditional功能,基于條件的自動(dòng)化配置。
2.SpringBoot自動(dòng)化配置UML圖解
SpringBootApplication是我們所常用熟知的注解,它是一個(gè)組合注解,依賴(lài)多個(gè)注解,共同實(shí)現(xiàn)SpringBoot應(yīng)用功能,以下為所有依賴(lài)的UML圖解,我們圍繞這些注解深入研究,看下具體的實(shí)現(xiàn)。
3.SpringBoot自動(dòng)化配置核心注解分析
SpringBootApplication注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters={@Filter(type=FilterType.CUSTOM,classes=TypeExcludeFilter.class),
@Filter(type=FilterType.CUSTOM,classes=AutoConfigurationExcludeFilter.class)})
@ConfigurationPropertiesScan
public@interfaceSpringBootApplication{
*需要排除的自動(dòng)化配置,根據(jù)類(lèi)名進(jìn)行排除,比如MongoAutoConfiguration,JpaRepositoriesAutoConfiguration等
@AliasFor(annotation=EnableAutoConfiguration.class)
Class[]exclude()default{};
*需要排除的自動(dòng)化配置,根據(jù)名稱(chēng)進(jìn)行排除
@AliasFor(annotation=EnableAutoConfiguration.class)
String[]excludeName()default{};
*指定需要掃描的包路徑,參數(shù)填寫(xiě)包名
@AliasFor(annotation=ComponentScan.class,attribute="basePackages")
String[]scanBasePackages()default{};
*指定需要掃描的包路徑
@AliasFor(annotation=ComponentScan.class,attribute="basePackageClasses")
Class[]scanBasePackageClasses()default{};
*Bean方法的動(dòng)態(tài)代理配置,如果沒(méi)有采用工廠(chǎng)方法,可以標(biāo)記為false,采用cglib代理。
@AliasFor(annotation=Configuration.class)
booleanproxyBeanMethods()defaulttrue;
}
3.1@Inherited
java.lang.annotation.@Inherited注解,從包名可以看出為JDK自帶注解,作用是讓子類(lèi)能夠繼承父類(lèi)中引用Inherited的注解,但需注意的是,該注解作用范圍只在類(lèi)聲明中有效;如果是接口與接口的繼承,類(lèi)與接口的繼承,是不會(huì)生效。
3.2@SpringBootConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(proxyBeanMethods=false)
public@interfaceSpringBootConfiguration{
*Bean方法的動(dòng)態(tài)代理配置
@AliasFor(annotation=Configuration.class)
booleanproxyBeanMethods()defaulttrue;
}
這是配置型處理注解,可以看到內(nèi)部源碼引用了@Configuration注解,
自身沒(méi)有太多的實(shí)現(xiàn),那為什么還需要再包裝?官方給出的解釋是對(duì)Spring的@Configuration的擴(kuò)展,
用于實(shí)現(xiàn)SpringBoot的自動(dòng)化配置。proxyBeanMethods屬性默認(rèn)為true,作用是對(duì)bean的方法是否開(kāi)啟代理方式調(diào)用,默認(rèn)為true,如果沒(méi)有采用工廠(chǎng)方法,可以設(shè)為false,通過(guò)cglib作動(dòng)態(tài)代理。
3.3@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public@interfaceEnableAutoConfiguration{
//設(shè)置注解支持重載的標(biāo)識(shí)
StringENABLED_OVERRIDE_PROPERTY="spring.boot.enableautoconfiguration";
*排除自動(dòng)化配置的組件,如MongoAutoConfiguration,JpaRepositoriesAutoConfiguration等
Class[]exclude()default{};
*排除自動(dòng)化配置的組件,根據(jù)名稱(chēng)設(shè)置
String[]excludeName()default{};
}
用于管理開(kāi)啟SpringBoot的各種自動(dòng)化配置注解,如datasource,mongodb,redis等,也是spring-boot-autoconfigure工程的核心注解。
AutoConfigurationPackage
它的主要作用是掃描主程序同級(jí)及下級(jí)的包路徑所有Bean與組件注冊(cè)到SpringIoc容器中。
Import
它可以把沒(méi)有聲明配置的類(lèi)注冊(cè)到SpringIoc容器中管理引用。導(dǎo)入的AutoConfigurationImportSelector類(lèi)實(shí)現(xiàn)BeanClassLoaderAware、ResourceLoaderAware、EnvironmentAware等接口,管理類(lèi)裝載器,資源裝載器及環(huán)境配置等,是一個(gè)負(fù)責(zé)處理自動(dòng)化配置導(dǎo)入的選擇管理器。在下面【@AutoConfigurationImportSelector剖析】進(jìn)行詳解。
3.4@ComponentScan
這是我們?cè)赟pring下面常用的一個(gè)注解,它可以?huà)呙鑃pring定義的注解,如@Componment,@Service等,常用的屬性有basePackages掃描路徑,includeFilters包含路徑過(guò)濾器,excludeFilters排除路徑過(guò)濾器,lazyInit是否懶加載等,能夠非常靈活的掃描管理需要注冊(cè)組件。
3.5@ConfigurationPropertiesScan
作用是掃描指定包及子包路徑下面的ConfigurationProperties注解,管理工程配置屬性信息。主要屬性為basePackages掃描路徑,支持多個(gè)路徑,數(shù)組形式;basePackageClasses屬性也可以具體到包下面的類(lèi),
支持多個(gè)配置。
3.6@AutoConfigurationImportSelector
AutoConfigurationImportSelector實(shí)現(xiàn)DeferredImportSelector、BeanClassLoaderAware、ResourceLoaderAware、BeanFactoryAware、EnvironmentAware、Ordered接口,為自動(dòng)化配置的核心處理類(lèi),主要負(fù)責(zé)自動(dòng)化配置規(guī)則的一系列處理邏輯:
/**
*{@linkDeferredImportSelector}tohandle{@linkEnableAutoConfiguration
*auto-configuration}.Thisclasscanalsobesubclassedifacustomvariantof
*{@linkEnableAutoConfiguration@EnableAutoConfiguration}isneeded.
*@authorPhillipWebb
*@authorAndyWilkinson
*@authorStephaneNicoll
*@authorMadhuraBhave
*@since1.3.0
*@seeEnableAutoConfiguration
publicclassAutoConfigurationImportSelectorimplementsDeferredImportSelector,BeanClassLoaderAware,
ResourceLoaderAware,BeanFactoryAware,EnvironmentAware,Ordered{
}
講解幾個(gè)技術(shù)點(diǎn):
getCandidateConfigurations方法
protectedListStringgetCandidateConfigurations(AnnotationMetadatametadata,AnnotationAttributesattributes){
ListStringconfigurations=SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations,"NoautoconfigurationclassesfoundinMETA-INF/spring.factories.Ifyou"
+"areusingacustompackaging,makesurethatfileiscorrect.");
returnconfigurations;
}
該方法是獲取所有SpringBoot聲明定義的自動(dòng)化配置類(lèi)。
看下具體有哪些信息:
這些實(shí)際是配置在Spring-boot-autoconfigure工程下的META-INF/spring.factories文件中:
看到這里,我們應(yīng)該可以明白,為什么AOP,RABBIT,DATASOURCE,REIDS等組件SPRINGBOOT都能幫我們快速配置實(shí)現(xiàn),其實(shí)它內(nèi)部遵循SPI機(jī)制,已經(jīng)把自動(dòng)化配置做好了封裝。
AutoConfigurationGroup類(lèi)
它是AutoConfigurationImportSelector的內(nèi)部類(lèi),實(shí)現(xiàn)了DeferredImportSelector.Group、BeanClassLoaderAware、BeanFactoryAware、ResourceLoaderAware接口,是一個(gè)重要的核心類(lèi)。主要作用是負(fù)責(zé)自動(dòng)化配置條目信息的記錄,排序,元數(shù)據(jù)處理等。它通過(guò)getImportGroup方法獲取返回,該方法實(shí)現(xiàn)DeferredImportSelector的接口。
privatestaticclassAutoConfigurationGroup
implementsDeferredImportSelector.Group,BeanClassLoaderAware,BeanFactoryAware,ResourceLoaderAware{
//記錄注解的元數(shù)據(jù)
privatefinalMapString,AnnotationMetadataentries=newLinkedHashMap();
//記錄自動(dòng)化配置條目,放入集合
privatefinalListAutoConfigurationEntryautoConfigurationEntries=newArrayList();
//設(shè)置bean的類(lèi)加載器
privateClassLoaderbeanClassLoader;
//設(shè)置bean工廠(chǎng)信息
privateBeanFactorybeanFactory;
//設(shè)置資源加載器信息
privateResourceLoaderresourceLoader;
//設(shè)置自動(dòng)化配置的元數(shù)據(jù)記錄
privateAutoConfigurationMetadataautoConfigurationMetadata;
}
屬性主要定義了一些自動(dòng)化配置類(lèi)目信息、BEAN工廠(chǎng)、類(lèi)和資源加載器信息。entries條目有22條,具體內(nèi)容如下:
里面是主要的自動(dòng)化配置類(lèi)的元數(shù)據(jù)信息,autoConfigurationEntries屬性就是具體的自動(dòng)化配置條目。這些主要自動(dòng)化類(lèi)配置是Springboot幫助我們實(shí)現(xiàn)mvc的核心功能,如請(qǐng)求分發(fā),文件上傳,參數(shù)驗(yàn)證,編碼轉(zhuǎn)換等功能。還有一部分是定制條件自動(dòng)化配置類(lèi),
autoConfigurationMetadata元數(shù)據(jù)內(nèi)容較多,包含各種組件,根據(jù)環(huán)境配置和版本不同,這里可以看到共有705個(gè):
由于SpringBoot支持眾多插件,功能豐富,數(shù)量較多;這里存在些疑問(wèn),這里面的元數(shù)據(jù)和上面的entries條目都是AutoConfiguration自動(dòng)化配置類(lèi),那有什么區(qū)別?其實(shí)這里面的,都是基于條件的自動(dòng)化配置。
我們就拿KafkaAutoConfiguration來(lái)看:
可以看到注解ConditionalOnClass,意思是KafkaAutoConfiguration生效的前提是基于KafkaTemplate類(lèi)的初始化成功,這就是定制條件,也就是基于條件的自動(dòng)化配置類(lèi),雖然有七百多個(gè),但其實(shí)是根據(jù)工程實(shí)際用到的組件,才會(huì)觸發(fā)加載對(duì)應(yīng)的配置。有關(guān)Conditional基于條件的自動(dòng)化配置實(shí)現(xiàn)原理,在下面我們?cè)僮魃钊胙芯俊?/p>
繼續(xù)看AutoConfigurationImportSelector內(nèi)部類(lèi)的selectImports方法:
@Override
publicIterableEntryselectImports(){
if(this.autoConfigurationEntries.isEmpty()){
returnCollections.emptyList();
//將所有自動(dòng)化條目根據(jù)配置的Exclusion條件作過(guò)濾,并轉(zhuǎn)換為SET集合
SetStringallExclusions=this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
//SET集合,記錄所有需要處理的自動(dòng)化配置
SetStringprocessedConfigurations=this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
//兩個(gè)SET,做交集過(guò)濾,排除不需要的配置
processedConfigurations.removeAll(allExclusions);
//最后進(jìn)行排序處理
returnsortAutoConfigurations(processedConfigurations,getAutoConfigurationMetadata()).stream()
.map((importClassName)-newEntry(this.entries.get(importClassName),importClassName))
.collect(Collectors.toList());
}
該方法是針對(duì)autoConfigurationEntries自動(dòng)化配置條目做過(guò)濾,根據(jù)指定的排除規(guī)則處理;再根據(jù)設(shè)置的啟動(dòng)的優(yōu)先級(jí)做排序整理。從代碼中可以看到,先獲取所有的allExclusions排除配置信息,再獲取所有需要處理的processedConfigurations配置信息,然后做過(guò)濾處理,最后再調(diào)用sortAutoConfigurations方法,根據(jù)order順序做排序整理。
AutoConfigurationImportSelector內(nèi)部類(lèi)的process方法:
@Override
publicvoidprocess(AnnotationMetadataannotationMetadata,DeferredImportSelectordeferredImportSelector){
Assert.state(deferredImportSelectorinstanceofAutoConfigurationImportSelector,
()-String.format("Only%simplementationsaresupported,got%s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
//獲取自動(dòng)化配置條目
AutoConfigurationEntryautoConfigurationEntry=((AutoConfigurationImportSelector)deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(),annotationMetadata);
//記錄獲取的條目
this.autoConfigurationEntries.add(autoConfigurationEntry);
for(StringimportClassName:autoConfigurationEntry.getConfigurations()){
//放入成員變量entries中
this.entries.putIfAbsent(importClassName,annotationMetadata);
}
該方法是掃描獲取autoConfigurationEntries自動(dòng)化配置條目信息。
annotationMetadata參數(shù):
為注解元數(shù)據(jù),有也就是被@SpringBootApplication修飾的類(lèi)信息,在這里就是我們的啟動(dòng)入口類(lèi)信息。
deferredImportSelector參數(shù):
通過(guò)@EnableAutoConfiguration注解定義的@Import的類(lèi),也就是AutoConfigurationImportSelector對(duì)象。根據(jù)配置,會(huì)加載指定的beanFactory、classLoader、resourceLoader和environment對(duì)象。
AutoConfigurationImportSelector內(nèi)部類(lèi)的getAutoConfigurationEntry方法:
protectedAutoConfigurationEntrygetAutoConfigurationEntry(AutoConfigurationMetadataautoConfigurationMetadata,
AnnotationMetadataannotationMetadata){
//1、判斷是否開(kāi)對(duì)應(yīng)注解
if(!isEnabled(annotationMetadata)){
returnEMPTY_ENTRY;
//2、獲取注解定義的屬性
AnnotationAttributesattributes=getAttributes(annotationMetadata);
//3、獲取符合規(guī)則的SpringBoot內(nèi)置的自動(dòng)化配置類(lèi),并做去重處理
ListStringconfigurations=getCandidateConfigurations(annotationMetadata,attributes);
configurations=removeDuplicates(configurations);
//4、做排除規(guī)則匹配,過(guò)濾處理
SetStringexclusions=getExclusions(annotationMetadata,attributes);
checkExcludedClasses(configurations,exclusions);
configurations.removeAll(exclusions);
configurations=filter(configurations,autoConfigurationMetadata);
//5、觸發(fā)自動(dòng)導(dǎo)入處理完成事件
fireAutoConfigurationImportEvents(configurations,exclusions);
returnnewAutoConfigurationEntry(configurations,exclusions);
}
該方法主要作用是獲取SpringBoot內(nèi)置的自動(dòng)化條目,例AopAutoConfiguration等,該方法會(huì)調(diào)用上面講解的getCandidateConfigurations方法。主要步驟邏輯如下:
判斷是否開(kāi)啟元注解掃描,對(duì)應(yīng)屬性為spring.boot.enableautoconfiguration,默認(rèn)情況下,是開(kāi)啟自動(dòng)配置。獲取定義的注解屬性,跟蹤內(nèi)部源碼,里面會(huì)返回exclude和excludeName等屬性。獲取符合規(guī)則的SpringBoot內(nèi)置的自動(dòng)化配置,并做去重處理,也就是我們上面講解的getCandidateConfigurations方法,從中我們就可以理解其中的關(guān)聯(lián)關(guān)系。做排除規(guī)則檢查與過(guò)濾處理,根據(jù)上面第2個(gè)步驟獲取的exclude等屬性以及配置屬性spring.autoconfigure.exclude做過(guò)濾處理。觸發(fā)自動(dòng)導(dǎo)入完成事件,該方法內(nèi)部邏輯正常處理完成才會(huì)觸發(fā),會(huì)調(diào)用AutoConfigurationImportListener監(jiān)聽(tīng)器做通知處理。
3.7@AutoConfigurationPackages
AutoConfigurationPackages是EnableAutoConfiguration上的另一個(gè)核心注解類(lèi),官方解釋為:
Indicatesthatthepackagecontainingtheannotatedclassshouldberegistered
意思是包含該注解的類(lèi),所在包下面的class,都會(huì)注冊(cè)到SpringIoc容器中。對(duì)應(yīng)源碼:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public@interfaceAutoConfigurationPackage{
Import注解,導(dǎo)入AutoConfigurationPackages抽象類(lèi)下面的內(nèi)部靜態(tài)類(lèi)Registrar,研究Registrar實(shí)現(xiàn)原理:
Registrar實(shí)現(xiàn)ImportBeanDefinitionRegistrar、DeterminableImports接口,它負(fù)責(zé)存儲(chǔ)從@AutoConfigurationPackage注解掃描到的信息。源碼如下:
staticclassRegistrarimplementsImportBeanDefinitionRegistrar,DeterminableImports{
//注冊(cè)BEAN的定義信息
@Override
publicvoidregisterBeanDefinitions(AnnotationMetadatametadata,BeanDefinitionRegistryregistry){
register(registry,newPackageImport(metadata).getPackageName());
//決定是否導(dǎo)入注解中的配置內(nèi)容
@Override
publicSetObjectdetermineImports(AnnotationMetadatametadata){
returnCollections.singleton(newPackageImport(metadata));
}
這里面主要涉及到PackageImport類(lèi),它是AutoConfigurationPackages的內(nèi)部私有靜態(tài)類(lèi),主要是記錄導(dǎo)入的報(bào)名信息,源碼如下:
/**
*Wrapperforapackageimport.
privatestaticfinalclassPackageImport{
privatefinalStringpackageName;
//構(gòu)造方法,記錄注解內(nèi)容
PackageImport(AnnotationMetadatametadata){
this.packageName=ClassUtils.getPackageName(metadata.getClassName());
//獲取指定包名稱(chēng)
publicStringgetPackageName(){
returnthis.packageName;
//重載父類(lèi)比較邏輯,根據(jù)包名判斷
@Override
publicbooleanequals(Objectobj){
if(obj==null||getClass()!=obj.getClass()){
returnfalse;
returnthis.packageName.equals(((PackageImport)obj).packageName);
//重載hash標(biāo)識(shí),以包名的HASH值為準(zhǔn)
@Override
publicinthashCode(){
returnthis.packageName.hashCode();
//重載toString,打印內(nèi)容
@Override
publicStringtoString(){
return"PackageImport"+this.packageName;
}
內(nèi)部斷點(diǎn)跟蹤的話(huà),可以看到它記錄的是我們啟動(dòng)類(lèi)所在的包名。這也就是為什么不需要指定掃描包路徑,也會(huì)加載啟動(dòng)類(lèi)所在包下面的JavaConfig配置信息。
回到上面Registrar的registerBeanDefinitions方法,內(nèi)部調(diào)用的是register方法:
它是處理記錄AutoConfigurationPackages掃描包信息,源碼如下:
publicstaticvoidregister(BeanDefinitionRegistryregistry,String...packageNames){
//判斷是否包含BEAN定義信息,如果包含,更新packageNames信息
if(registry.containsBeanDefinition(BEAN)){
BeanDefinitionbeanDefinition=registry.getBeanDefinition(BEAN);
ConstructorArgumentValuesconstructorArguments=beanDefinition.getConstructorArgumentValues();
constructorArguments.addIndexedArgumentValue(0,addBasePackages(constructorArguments,packageNames));
//如果registry中
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 技術(shù)員轉(zhuǎn)正工作總結(jié)模版
- 供貨瓷磚合同范例
- 會(huì)計(jì)從業(yè)資格考試會(huì)計(jì)基礎(chǔ)復(fù)習(xí)重點(diǎn)知識(shí)總結(jié)模版
- 企業(yè)贊助演出合同范例
- 醫(yī)療行業(yè)績(jī)效評(píng)估的未來(lái)趨勢(shì)與挑戰(zhàn)
- 侵權(quán)模仿責(zé)任合同范例
- 醫(yī)院后勤物資管理的透明化改革
- 醫(yī)院文化建設(shè)的核心價(jià)值觀(guān)及其實(shí)踐路徑
- 區(qū)塊鏈驅(qū)動(dòng)的跨境貿(mào)易融資解決方案
- 醫(yī)療設(shè)備行業(yè)趨勢(shì)預(yù)測(cè)與戰(zhàn)略規(guī)劃
- 消防維??己藰?biāo)準(zhǔn)
- 【初中化學(xué)】常見(jiàn)的鹽-2024-2025學(xué)年九年級(jí)化學(xué)科粵版(2024)下冊(cè)
- 杭州職高招生試題及答案
- 中國(guó)教育社會(huì)問(wèn)題
- 2024江蘇南通高新控股集團(tuán)及下屬子企業(yè)招聘9人筆試參考題庫(kù)附帶答案詳解
- 食品合規(guī)管理職業(yè)技能等級(jí)標(biāo)準(zhǔn)
- 2025年美術(shù)國(guó)家考試試題及答案
- 特種設(shè)備重大事故隱患判定準(zhǔn)則
- 貝葉斯時(shí)間序列分析-深度研究
- 學(xué)校物業(yè)假期管理制度
- 學(xué)前教育專(zhuān)業(yè)實(shí)習(xí)總結(jié)
評(píng)論
0/150
提交評(píng)論