原创不易,转载请写明出处
这个地方涉及到 spring boot 自动配置,就先聊聊spring boot的自动配置原理,在sping boot 的自动配置中,最重要的注解是如下注解,保留核心代码
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
看看 EnableAutoConfigurationImportSelector的代码实现,也是保留核心逻辑
public class EnableAutoConfigurationImportSelector implements DeferredImportSelector{
@Override
public String[] selectImports(AnnotationMetadata metadata) {
List configurations = getCandidateConfigurations(metadata, attributes);
return configurations.toArray(new String[configurations.size()]);
}
}
下面贴出getCandidateConfigurations()方法的代码实现,也是保留核心逻辑
protected List getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes) {
List configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
return configurations;
}
这个地方 getSpringFactoriesLoaderFactoryClass()获取的是 EnableAutoConfiguration.class,也就是上面的自动配置的注解
再来看看SpringFactoriesLoader类中的 loadFactoryNames()方法
public static ListloadFactoryNames(Class factoryClass, ClassLoader classLoader) {
// 这个地方是 org.springframework.boot.autoconfigure.EnableAutoConfiguration
String factoryClassName = factoryClass.getName();
// FACTORIES_RESOURCE_LOCATION 的内容是"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的资源,之后读取文件转化为properties 文件获取key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的value,之后把逗号分隔的字符串转化为数组,返回,返回的数组内容就是要初始化的配置类的名字,下面截取了spring-boot-autoconfigure包中的文件spring.factories 返回的数组
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
最后一个是比较重要的配置,数据源的自动配置,有兴趣可以自己看一下,上面说了spring-boot的自动配置原理,下面看看mybatis-spirng-boot-autoconfigure的自动配置原理,这个包主要依赖了 mybatis, 以及 mybatis-spring,它的 META-INF/spring.factories中的内容为
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
也就是说,在spring-boot添加@EnableAutoConfiguration注解时,会去自动实例化 org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration类
MybatisAutoConfiguration类中,主要核心逻辑如下
// 很重要的方法,读取yml初始化SqlSessionFactory, 采用的是默认实现类 DefaultSqlSessionFactory,
// 在SqlSessionFactoryBuilder 中的 build(Configuration)
@Bean
@ConditionalOnMissingBean
public SqlSessionFactorysqlSessionFactory(DataSource dataSource)throws Exception {
// 项目启动的时候初始化 SqlSessionFactoryBean,设置成员变量,这个成员变量是从yml等配置文件读来的,也就是spring boot
SqlSessionFactoryBean factory =new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setVfs(SpringBootVFS.class);
//设置springBoot解析的配置,可以设置configLocation,也可以设置configuration,只能设置其一
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,自动注入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);
}
}