mybatis源码学习-自动配置原理

原创不易,转载请写明出处

这个地方涉及到 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);

    }

}

你可能感兴趣的:(mybatis源码学习-自动配置原理)