原創(chuàng)不易能扒,轉(zhuǎn)載請(qǐng)寫(xiě)明出處
這個(gè)地方涉及到 spring boot 自動(dòng)配置辫狼,就先聊聊spring boot的自動(dòng)配置原理初斑,在sping boot 的自動(dòng)配置中见秤,最重要的注解是如下注解,保留核心代碼
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
看看?EnableAutoConfigurationImportSelector的代碼實(shí)現(xiàn)测摔,也是保留核心邏輯
public class EnableAutoConfigurationImportSelector implements DeferredImportSelector{
@Override
public String[] selectImports(AnnotationMetadata metadata) {
? ? List?configurations = getCandidateConfigurations(metadata, attributes);
? ? ?return configurations.toArray(new String[configurations.size()]);
? }
}
下面貼出getCandidateConfigurations()方法的代碼實(shí)現(xiàn)解恰,也是保留核心邏輯
protected List?getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes) {
? ? ?List configurations = SpringFactoriesLoader.loadFactoryNames(
? ? ?getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
? ? ?return configurations;
}
這個(gè)地方 getSpringFactoriesLoaderFactoryClass()獲取的是?EnableAutoConfiguration.class修噪,也就是上面的自動(dòng)配置的注解
再來(lái)看看SpringFactoriesLoader類中的?loadFactoryNames()方法
public static ListloadFactoryNames(Class factoryClass, ClassLoader classLoader) {
// 這個(gè)地方是?org.springframework.boot.autoconfigure.EnableAutoConfiguration
String factoryClassName = factoryClass.getName();
//? FACTORIES_RESOURCE_LOCATION 的內(nèi)容是"META-INF/spring.factories"
Enumeration urls = (classLoader !=null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
? ? ? List result =new ArrayList();
? ? ? while (urls.hasMoreElements()) {
? ? ? URL url = urls.nextElement();
? ? ? ? Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
? ? ? ? String factoryClassNames = properties.getProperty(factoryClassName);
? ? ? ? result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
? ? ? }
return result;
}
以上代碼做的事情就是獲取類加載器classLoader下,所有的資源名為META-INF/spring.factories的資源路媚,之后讀取文件轉(zhuǎn)化為properties 文件獲取key為org.springframework.boot.autoconfigure.EnableAutoConfiguration的value黄琼,之后把逗號(hào)分隔的字符串轉(zhuǎn)化為數(shù)組,返回整慎,返回的數(shù)組內(nèi)容就是要初始化的配置類的名字脏款,下面截取了spring-boot-autoconfigure包中的文件spring.factories 返回的數(shù)組
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
最后一個(gè)是比較重要的配置,數(shù)據(jù)源的自動(dòng)配置裤园,有興趣可以自己看一下撤师,上面說(shuō)了spring-boot的自動(dòng)配置原理,下面看看mybatis-spirng-boot-autoconfigure的自動(dòng)配置原理拧揽,這個(gè)包主要依賴了 mybatis剃盾, 以及 mybatis-spring,它的?META-INF/spring.factories中的內(nèi)容為?
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
也就是說(shuō),在spring-boot添加@EnableAutoConfiguration注解時(shí)淤袜,會(huì)去自動(dòng)實(shí)例化?org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration類
MybatisAutoConfiguration類中痒谴,主要核心邏輯如下
// 很重要的方法,讀取yml初始化SqlSessionFactory, 采用的是默認(rèn)實(shí)現(xiàn)類 DefaultSqlSessionFactory铡羡,
// 在SqlSessionFactoryBuilder 中的 build(Configuration)
@Bean
@ConditionalOnMissingBean
public SqlSessionFactorysqlSessionFactory(DataSource dataSource)throws Exception {
// 項(xiàng)目啟動(dòng)的時(shí)候初始化 SqlSessionFactoryBean积蔚,設(shè)置成員變量,這個(gè)成員變量是從yml等配置文件讀來(lái)的烦周,也就是spring boot
? ? SqlSessionFactoryBean factory =new SqlSessionFactoryBean();
? ? factory.setDataSource(dataSource);
? ? factory.setVfs(SpringBootVFS.class);
? ? //設(shè)置springBoot解析的配置,可以設(shè)置configLocation,也可以設(shè)置configuration,只能設(shè)置其一
? ? if (StringUtils.hasText(this.properties.getConfigLocation())) {
factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
? ? }
factory.setConfiguration(properties.getConfiguration());
? ? if (this.properties.getConfigurationProperties() !=null) {
factory.setConfigurationProperties(this.properties.getConfigurationProperties());
? ? }
if (!ObjectUtils.isEmpty(this.interceptors)) {
factory.setPlugins(this.interceptors);
? ? }
if (this.databaseIdProvider !=null) {
factory.setDatabaseIdProvider(this.databaseIdProvider);
? ? }
if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
? ? }
if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
? ? }
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
factory.setMapperLocations(this.properties.resolveMapperLocations());
? ? }
// springBoot配置完成后解析config.xml
? ? return factory.getObject();
}
// 初始化 sqlSessionTemplate,自動(dòng)注入sqlSessionFactory
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplatesqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
ExecutorType executorType =this.properties.getExecutorType();
? ? if (executorType !=null) {
return new SqlSessionTemplate(sqlSessionFactory, executorType);
? ? }else {
return new SqlSessionTemplate(sqlSessionFactory);
? ? }
}