簡(jiǎn)單詳細(xì)的SpringBoot自動(dòng)配置原理解析
文章目錄
前言
環(huán)境
從啟動(dòng)類開(kāi)始
@SpringBootApplication
@EnableAutoConfiguration
AutoConfigurationImportSelector的selectImports方法
配置類注冊(cè)到IOC容器的流程圖
以DataSourceAutoConfiguration進(jìn)行說(shuō)明
DataSourceProperties 類
DataSourcePoolMetadataProvidersConfiguration 類
總結(jié)
前言
上一篇文章我們介紹了SpringFactoriesLoader,之所以介紹SpringFactoriesLoader是因?yàn)槲覀冞@篇文章要介紹的SpringBoot的自動(dòng)配置會(huì)用到SpringFactoriesLoader的知識(shí)。閑話少敘,讓我們直入主題。
環(huán)境
spring-boot 1.5.8.RELEASE
從啟動(dòng)類開(kāi)始
@SpringBootApplication
public class HelloworldDemoApplication {
public static void main(String[] args) {
SpringApplication.run(HelloworldDemoApplication.class, args);
}
}
如上,就是我們SpringBoot應(yīng)用的啟動(dòng)類。讓我們把眼光聚焦到@SpringBootApplication注解上面。這個(gè)注解是SpringBoot項(xiàng)目的主配置類。
@SpringBootApplication
//省略部分注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
根據(jù)前幾篇的介紹,我們可以知道@SpringBootApplication注解是一個(gè)組合注解。
@SpringBootConfiguration注解 表示這是SpringBoot的配置類,
@ComponentScan 開(kāi)啟組件掃描
@EnableAutoConfiguration這個(gè)注解的作用就是讓SpringBoot開(kāi)啟自動(dòng)配置。自動(dòng)配置的奧秘全都在這里:
@EnableAutoConfiguration
//省略部分注解
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
如上我們可以看到EnableAutoConfiguration注解上有兩個(gè)注解
@AutoConfigurationPackage 注解,
從字面意思上來(lái)看就是自動(dòng)配置包。點(diǎn)進(jìn)去可以看到就是?個(gè) @Import 注解: @Import(AutoConfigurationPackages.Registrar.class) ,導(dǎo)?了?個(gè)
Registrar 的組件,這個(gè)注解的作用就是將主配置類(@SpringBootConfiguration標(biāo)注的類)所在的包及其下面所有子包里面所有的組件掃描到IOC容器中。所以說(shuō),默認(rèn)情況下主配置類所在包及其子包以外的組件,Spring IOC容器是掃描不到的。
@Import(AutoConfigurationImportSelector.class)
通過(guò)@Import導(dǎo)入了AutoConfigurationImportSelector類,而這個(gè)類的selectImports方法會(huì)通過(guò)SpringFactoriesLoader得到大量的配置類。而每個(gè)配置類則根據(jù)條件化配置類做出決策,以實(shí)現(xiàn)自動(dòng)配置的功能。下面就讓我們來(lái)看看selectImports方法。
AutoConfigurationImportSelector的selectImports方法
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//省略部分代碼
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
return StringUtils.toStringArray(configurations);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
return configurations;
}
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
如上代碼,自動(dòng)配置核心的代碼我都羅列出來(lái)了,最核心的就是loadFactoryNames方法,其主要有三步:
從classpath下獲取所有META-INF/spring.factories這個(gè)文件下的信息。
將上面獲取到的信息封裝成Enumeration返回
遍歷Enumeration,然后獲取key為EnableAutoConfiguration下的所有值。
META-INF/spring.factories 這類?件是什么就不懵了。當(dāng)然在很多第三?依賴中
都會(huì)有這個(gè)?件,?般每導(dǎo)??個(gè)第三?的依賴,除了本?的jar包以外,還會(huì)有?個(gè) xxx-spring-boot-autoConfigure,這個(gè)就
是第三?依賴??編寫(xiě)的?動(dòng)配置類。我們現(xiàn)在就以 spring-boot-autocongigure 這個(gè)依賴來(lái)說(shuō)下,其下面的META-INF/spring.factories文件。
Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
配置類注冊(cè)到IOC容器的流程圖
然后就是實(shí)例化這些配置類注冊(cè)到IOC容器中。流程如下:
以DataSourceAutoConfiguration進(jìn)行說(shuō)明
通過(guò)上面的方式,所有的自動(dòng)配置類都被導(dǎo)進(jìn)主配置類中,但是這么多的配置類,明顯有很多我們平常是沒(méi)有使用到的,沒(méi)必要全部生效,下面我們以DataSourceAutoConfiguration配置類為例來(lái)看一下自動(dòng)配置類是如何工作的:
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
}
@Configuration
注解表明了DataSourceAutoConfiguration類是一個(gè)JavaConfig配置類。@ConditionalOnClass只有當(dāng)classpath中存在DataSource類或者EmbeddedDatabaseType類時(shí)才啟動(dòng)這個(gè)配置。@EnableConfigurationProperties這個(gè)注解的作用是將將DataSource類注入到IOC容器中。@Import({
Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class
})是要導(dǎo)入額外的配置DataSourcePoolMetadataProvidersConfiguration。
DataSourceProperties 類
下面我們就來(lái)一個(gè)個(gè)看一下:首先是DataSourceProperties類:
@ConfigurationProperties(prefix = “spring.datasource”)
public class DataSourceProperties
implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
private ClassLoader classLoader;
private Environment environment;
private String name = "testdb";
private boolean generateUniqueName;
private Class<? extends DataSource> type;
private String driverClassName;
private String url;
}
DataSourceProperties
通過(guò)@ConfigurationProperties注解將配置文件的前綴為(spring.datasource)的配置信息與自身的屬性綁定。所有在配置?件中能配置的屬性都是在
xxxProperties 類中封裝著;配置?件能配置什么就可以參照某個(gè)功能對(duì)應(yīng)的這個(gè)屬性
類。
DataSourcePoolMetadataProvidersConfiguration 類
@Configuration
public class DataSourcePoolMetadataProvidersConfiguration {
@Configuration
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
static class TomcatDataSourcePoolMetadataProviderConfiguration {
}
@Configuration
@ConditionalOnClass(HikariDataSource.class)
static class HikariPoolDataSourceMetadataProviderConfiguration {
DataSourcePoolMetadataProvidersConfiguration
類是數(shù)據(jù)庫(kù)連接池提供者的一個(gè)配置類。即classpath中存在org.apache.tomcat.jdbc.pool.DataSource.class則使?tomcat-jdbc連接池,如果classpath中存在
HikariDataSource.class則使?
Hikari連接池,如果存在org.apache.commons.dbcp.BasicDataSource.class則啟用dbcp 連接池。
總結(jié)
SpringBoot啟動(dòng)時(shí)會(huì)掃描項(xiàng)目所依賴的JAR包,尋找包含spring.factories文件的JAR包。
根據(jù)spring.factories配置加載EnableAutoConfiguration
其中給容器中自動(dòng)配置添加組件的時(shí)候,會(huì)從propeties類中獲取配置文件中指定這些屬性的值。xxxAutoConfiguration:?動(dòng)配置類給容器中添加組件。xxxProperties:封裝配置?件中相關(guān)屬性。
根據(jù)@Conditional注解的條件,進(jìn)行自動(dòng)配置并將Bean注入Spring容器
作者:碼農(nóng)飛哥
微信公眾號(hào):碼農(nóng)飛哥
