1. 依賴管理
SpringBoot 最方便的地方就是 自動配置 和 互補(bǔ)配置,而自動配置的前提是有這些東西才能配置,也就是必須要有相應(yīng)的依賴。
SpringBoot 有各種各樣的場景啟動器,這些啟動器里邊根據(jù)場景的需求幫我們引入了各種依賴。
所以我們只需要對應(yīng)場景選擇啟動器即可完成大多數(shù)依賴的引入,而且spring-boot-starter-parent => spring-boot-dependencies 里面定義了依賴相應(yīng)的m默認(rèn)版本,但是我們又能夠自定義版本。
各種場景啟動器都會依賴spring-boot-starter,而spring-boot-starter 又會依賴 spring-boot-autoconfigure,后者就是用于自動配置的。
總之:
- 場景啟動器里邊配置依賴;
- 場景啟動器所依賴的 spring-boot-autoconfigure 幫助自動配置;
- 父項(xiàng)目中的 spring-boot-dependencies 管理依賴的版本
2. 自動配置
自動配置的誤區(qū):剛學(xué) springBoot 的時候,認(rèn)為有 @Component、@Configuration 注解的類,程序不就自動注入了么,還管什么自動配置???
這種觀點(diǎn)是片面的,上面的自動注入有一個前提,那就是類需要在掃描包的范圍之內(nèi)(也就是@SpringBootApplication主配置類同級及以下的目錄),但是如果我們引入其他依賴,即使類上面有 @Component 注解,也無法自動注入,因?yàn)樗辉趻呙璋姆秶畠?nèi)。
所以這種情況,就需要借助 springBoot 的自動配置原理,進(jìn)行輔助,完成自動注入。
2.0 幾種自動配置的方式列舉
1)上面說到,無法完成自動注入是因?yàn)椴辉趻呙璋秶畠?nèi),那最直接的方法就是把類納入到掃描范圍
使用 @ComponentScan 增加掃描的范圍
2)@AutoConfiguration + META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
就是 @AutoConfiguration 配置在類上面,然后在 org.springframework.boot.autoconfigure.AutoConfiguration.imports 配置文件中配置這個類的全限定類名。2.7.0 之前版本也兼容
但是實(shí)測,@AutoConfiguration 可以不加,甚至 @Component 也可以不加,只需要 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件配置就行,但如果需要控制加載順序,則可借助 @AutoConfiguration 或者 @AutoConfigureBefore、@AutoConfigureAfter
對于 2.7.0 之前的 springBoot 是另一種方式:@Configuration + META-INF/spring.factories 文件中的 org.springframework.boot.autoconfigure.EnableAutoConfiguration 屬性配置全類名(可能意識到需要自動注入的類太多,干脆直接搞一個單獨(dú)維護(hù)自動配置類的文件了:org.springframework.boot.autoconfigure.AutoConfiguration.imports)
3)對于已經(jīng)有 @AutoConfiguration 注解的類,如果某些類依賴于它(也就是這個類注入了,某些類注入才有意義),或者這個類依賴某些其他類(例如注入的成員變量),這種情況可以借助 @Import 注解
有三種方式:
1.直接在 @Import 的 value 中加入依賴或被依賴的類
2.自定義導(dǎo)入類實(shí)現(xiàn) ImportSelector 接口,并加入到 @Import 的 value 中
3.自定義導(dǎo)入類實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口,并加入到 @Import 的 value 中
后兩種方法,適用于較多的情況。
值得注意的是,如果沒有指定順序(可以使用@Component + @Order), @Import 是按照 value 數(shù)組的順序注入的
4)原生 servlet 注入
@ImportResource 用于指定 xml 位置,用于自動注入
5)對于配置類
這種情況可以使用:@ConfigurationProperties(放在配置類上) + @EnableConfigurationProperties(放在自動注入的類上)
2.1 關(guān)于容器注入和屬性綁定的幾種注解
1) @Configuration + @Bean
@Configuration 標(biāo)注在配置類上,聲明這個類是一個配置類,本質(zhì)上也是容器中的組件(@Component)。其中一個屬性proxyBeanMethods,默認(rèn)為true,含義是是否需要代理,就是是否為單例,true 代表單例,false 代表不是單例。
@Bean 標(biāo)注在配置類方法上,用于給容器中注入組件,類型為方法返回值類型,組件名稱默認(rèn)為方法名,也可以自定義組件名。
2)@Import
標(biāo)注在類上,也是為容器中注入組件,前提是該類也是容器中的一個組件(@Configuration,@Component 等等都實(shí)行),屬性 value 是一個 Class 數(shù)組,用于指定注入哪些類型的組件,組件名和類同名但首字母小寫。
通常直接在 @Import 的 value 中指定需要導(dǎo)入的類型即可,但有的時候類型太多或者不固定,就不適合直接寫導(dǎo)入的類了,可以用下面兩種方法。
a. 借助 ImportSelector
實(shí)現(xiàn) ImportSelector 接口,它有一個 selectImports 方法,用于返回想要導(dǎo)入的容器的全類名字符串?dāng)?shù)組。使用時只要把這個 Selector 填入 @Import 即可借助 @Import 將這些類注入
public interface ImportSelector {
String[] selectImports(AnnotationMetadata var1);
@Nullable
default Predicate<String> getExclusionFilter() {
return null;
}
}
// demo
public class DemoSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {
Demo.class.getName() // 需要導(dǎo)入的類都加入到這個數(shù)組即可
};
}
}
b. 借助 ImportBeanDefinitionRegistrar
實(shí)現(xiàn) ImportBeanDefinitionRegistrar,實(shí)現(xiàn) registerBeanDefinitions 方法,利用 registry.registerBeanDefinition() 將想要注入的組件注冊,然后將這個 Registar 填入 @Import value 中即可。
ImportSelector 中按照全限定類名注入,中間對于bean沒有什么操作空間。相對于實(shí)現(xiàn) ImportSelector,實(shí)現(xiàn) ImportBeanDefinitionRegistrar 稍微麻煩一點(diǎn),但是注入bean之前可以做更多事。
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
this.registerBeanDefinitions(importingClassMetadata, registry);
}
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
//例子
public class SelfImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//想要住放入的類,需要通過 BeanDefinition 包裝一下,
RootBeanDefinition root = new RootBeanDefinition(Test.class);
registry.registerBeanDefinition("組件名", root);
}
}
3)@Conditional
標(biāo)注與配置類或組件上面(@Configuration, @Bean...),用于條件裝配,滿足一定條件才注入,

4)@ImportResource
用于引入原生的配置文件。如 XXX.xml 這種形式的文件,里面注入的組件,SpringBoot 是不能直接獲取的,利用這個注解,可以使其生效,屬性 locations 是配置文件路徑的字符數(shù)組。
@ImportResource("classpath:beans.xml")
5)@ConfigurationProperties,@Value
@Value 標(biāo)注在屬性上,從配置文件中讀取數(shù)據(jù)賦值給屬性@ConfigurationProperties 標(biāo)注類上,可以從配置文件中讀取信息,綁定到類的屬性中,使其生效的方法有兩種:
a. 標(biāo)注在組件上
也就是說這個類不止要被 @ConfigurationProperties 修飾,還要是一個組件(@Configuration,@Component...)。
b. 配合 @EnableConfigurationProperties
在某個配置類上,用 @EnableConfigurationProperties 標(biāo)注,并把 @ConfigurationProperties 標(biāo)注的類的 class 填入到 @EnableConfigurationProperties 的屬性中即可。
這個注解有兩個作用:
1、開啟 @ConfigurationProperties 標(biāo)注類的配置綁定功能
2、把這個類的組件自動注冊到容器中
6)@ComponentScan
用來指定 Spring 掃描的包,也就是掃描范圍,默認(rèn)是 @Component 注解所在的同級及以下目錄
2.2 自動注入的關(guān)鍵,@SpringBootApplication
//說明@SpringBootApplication也是個配置類
@SpringBootConfiguration
//開啟自動配置
@EnableAutoConfiguration
//包掃描
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@ComponentScan 在不指定掃描路徑的情況下,默認(rèn)掃描標(biāo)注類的同級及以下的路徑??梢酝ㄟ^ @SpringBootApplication 的 scanBasePages 屬性自定義掃描路徑。
//自動配置包
@AutoConfigurationPackage
//導(dǎo)入一個 Selector
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
導(dǎo)入了一個 AutoConfigurationImportSelector 組件,這個組件會總 "META-INF/spring.factories" 文件中讀取 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的值,里邊是各種 XXXAutoConfiguration的全類名。所以它就是用來幫我們導(dǎo)入大量的配置類的。
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
這里又導(dǎo)入了一個 AutoConfigurationPackages.Registrar,這個大致就是為當(dāng)前項(xiàng)目包下的所有組件,如果配置了 scanBasePackages 就用配置的包,沒有配置就用主配置類所在的包。
總結(jié):
@SpringBootApplication 幫我們開啟了自動配置和組件導(dǎo)入。
借助 @Import 和 AutoConfigurationImportSelector 導(dǎo)入各種 AutoConfiguration 組件,用于自動配置。
借助 @Import 和 AutoConfigurationPackages.Registrar 導(dǎo)入當(dāng)前項(xiàng)目包路徑中的組件。
3. 自動配置
@SpringBootApplication 從 spring-boot-autoconfigure 中獲取并注入各種 AutoConfiguration 組件,用來自動配置,里邊會利用 2.1 中的幾種注解實(shí)現(xiàn)自動配置,互補(bǔ)配制和條件裝配。例如:Servlet 容器自動配置的例子解析