0 @SpringBootApplication
標(biāo)識(shí)被注解的類是一個(gè)
@Configuration
類蔬啡,在類中可以聲明一個(gè)或多個(gè)@bean
方法,并且它會(huì)觸發(fā)@EnableAutoConfiguration
和@ComponenetScan
的相應(yīng)功能。@SpringBootApplication
注解是一個(gè)綜合性注解盒让,等同于聲明@Configuration
刨裆、@EnableAutoConfiguration
和@ComponentScan
這三個(gè)注解告唆。
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ...
}
在 @SpringBootApplication
的類聲明中沒有看到 @Configuration
注解,那是因?yàn)?@SpringBootConfiguration
其實(shí)就是一個(gè) @Configuration`` 注解簇秒。至于
@EnableAutoConfiguration``` 注解的魔法功能在下面會(huì)說到鱼喉。
這篇文章不談?wù)摼唧w背后的工作原理,只是先認(rèn)識(shí)跟 @SpringBootApplication
注解相關(guān)的其他幾個(gè)注解趋观,以及帶來(lái)的作用蒲凶。先把地基打好,才能建高樓大廈拆内。
1 @Import
@Import 注解標(biāo)識(shí)可以導(dǎo)入一個(gè)或多個(gè) @Configuration 類。它提供的功能等同于以前 spring xml 配置中的
<import />
標(biāo)簽宠默,可以導(dǎo)入 @Configuration 類麸恍、ImportSelector 和 ImportBeanDefinitionRegistrar 的實(shí)現(xiàn)類,以及普通的組件類搀矫。如果 XML 或其他非 @Configuration 定義的 bean 資源需要被導(dǎo)入抹沪,可以使用 @ImportResource 注解。
1.1 ImportSelector
public interface ImportSelector {
/**
* 基于正在導(dǎo)入的 @Configuration 的 AnnotationMetadata 來(lái)選擇應(yīng)該被導(dǎo)入的類的名字
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
ImportSelector 的子類可以實(shí)現(xiàn)任何下列
org.springframework.beans.factory.Aware Aware
接口瓤球,它們各自的方法都會(huì)在selectImports()
方法之前被調(diào)用融欧。
org.springframework.context.EnvironmentAware
org.springframework.beans.factory.BeanFactoryAware
org.springframework.beans.factory.BeanClassLoaderAware
org.springframework.context.ResourceLoaderAware
1.2 ImportBeanDefinitionRegistrar
public interface ImportBeanDefinitionRegistrar {
/**
* 基于正在導(dǎo)入的 @Configuration 的給定的注解元數(shù)據(jù)來(lái)注冊(cè) bean definition
* bean definition 其實(shí)就是對(duì) bean 的元數(shù)據(jù)信息封裝。
* 需要注意的是卦羡,BeanDefinitionRegistryPostProcessor 類型不會(huì)在這里注冊(cè)噪馏,因?yàn)? * 生命周期相關(guān)的約束。
*/
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
在處理 @Configuration 時(shí)绿饵,注冊(cè)額外的 bean definition欠肾。
2 @EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
開啟 Spring 應(yīng)用上下文的自動(dòng)配置功能,它試圖猜測(cè)你可能需要配置的 bean拟赊。
2.1 @AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
表示包含該注解的類所在的包應(yīng)該在 AutoConfigurationPackages 中注冊(cè)刺桃。所以這個(gè)注解就能夠解釋為什么 spring boot 的啟動(dòng)類要放在 package 的最為層,以保證 spring 能夠自動(dòng)掃描到它們吸祟。
它的實(shí)現(xiàn)原理是在注解上標(biāo)注了 @Import瑟慈,導(dǎo)入了一個(gè)AutoConfigurationPackages.Registrar
桃移。
2.1.1 AutoConfigurationPackages.Registrar
用于保存導(dǎo)入的配置類所在的根包。它實(shí)現(xiàn)了 ImportBeanDefinitionRegistrar 接口葛碧。注意下借杰,Registrar 類是 AutoConfigurationPackages 類的內(nèi)部類,跟上面的注解 @AutoConfigurationPackage 名字就差了一個(gè)字母吹埠,別搞混了第步。
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
2.2 AutoConfigurationImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
// ...
}
DeferredImportSelector 用于處理自動(dòng)配置。如果需要自定義擴(kuò)展 @EnableAutoConfiguration缘琅,那么也可以擴(kuò)展此類粘都。
2.2.1 DeferredImportSelector
public interface DeferredImportSelector extends ImportSelector {
// ...
}
DeferredImportSelector
接口是ImportSelector
接口的一種擴(kuò)展,它是在處理完所有 @Configuration 類型的 bean 之后才會(huì)被執(zhí)行刷袍,因此翩隧,它的執(zhí)行時(shí)機(jī)是在@Configuration
注解中的其他邏輯被處理完畢之后(包括對(duì)@ImportResource
、@Bean
這些注解的處理)再執(zhí)行呻纹,也就是說堆生,DeferredImportSelector
的執(zhí)行時(shí)機(jī)比ImportSelector
更晚。
DeferredImportSelector
接口在處理有條件的選擇導(dǎo)入時(shí)非常有用雷酪。