zoukankan      html  css  js  c++  java
  • springboot集成mybatis源码分析-启动加载mybatis过程(二)

    1、springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解@SpringBootApplication中的@EnableAutoConfiguration

    2、EnableAutoConfiguration主要是通过AutoConfigurationImportSelector类来加载

      以mybatis为例,*selector通过反射加载spring.factories中指定的java类,也就是加载MybatisAutoConfiguration类(该类有Configuration注解,属于配置类)

      

      

      

     16 package org.mybatis.spring.boot.autoconfigure; 60 重点:SqlSessionFactory 和 SqlSessionTemplate 两个类
     61 /**
     62  * {@link EnableAutoConfiguration Auto-Configuration} for Mybatis. Contributes a
     63  * {@link SqlSessionFactory} and a {@link SqlSessionTemplate}.
     64  *
     65  * If {@link org.mybatis.spring.annotation.MapperScan} is used, or a
     66  * configuration file is specified as a property, those will be considered,
     67  * otherwise this auto-configuration will attempt to register mappers based on
     68  * the interface definitions in or under the root auto-configuration package.
     69  *
     70  * @author Eddú Meléndez
     71  * @author Josh Long
     72  * @author Kazuki Shimizu
     73  * @author Eduardo Macarrón
     74  */
     75 @org.springframework.context.annotation.Configuration
     76 @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
     77 @ConditionalOnBean(DataSource.class)
     78 @EnableConfigurationProperties(MybatisProperties.class)
     79 @AutoConfigureAfter(DataSourceAutoConfiguration.class)
     80 public class MybatisAutoConfiguration {
     81 
     82   private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);
     83  //与mybatis配置文件对应
     84   private final MybatisProperties properties;
     85 
     86   private final Interceptor[] interceptors;
     87 
     88   private final ResourceLoader resourceLoader;
     89 
     90   private final DatabaseIdProvider databaseIdProvider;
     91 
     92   private final List<ConfigurationCustomizer> configurationCustomizers;
     93 
     94   public MybatisAutoConfiguration(MybatisProperties properties,
     95                                   ObjectProvider<Interceptor[]> interceptorsProvider,
     96                                   ResourceLoader resourceLoader,
     97                                   ObjectProvider<DatabaseIdProvider> databaseIdProvider,
     98                                   ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
     99     this.properties = properties;
    100     this.interceptors = interceptorsProvider.getIfAvailable();
    101     this.resourceLoader = resourceLoader;
    102     this.databaseIdProvider = databaseIdProvider.getIfAvailable();
    103     this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
    104   }
    105  //postConstruct作用是在创建类的时候先调用,  校验配置文件是否存在
    106   @PostConstruct
    107   public void checkConfigFileExists() {
    108     if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
    109       Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
    110       Assert.state(resource.exists(), "Cannot find config location: " + resource
    111           + " (please add config file or check your Mybatis configuration)");
    112     }
    113   }
    114   //conditionalOnMissingBean作用:在没有类的时候调用,创建sqlsessionFactory  sqlsessionfactory最主要的是创建并保存了Configuration类
    115   @Bean
    116   @ConditionalOnMissingBean
    117   public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    118     SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    119     factory.setDataSource(dataSource);
    120     factory.setVfs(SpringBootVFS.class);
    121     if (StringUtils.hasText(this.properties.getConfigLocation())) {
    122       factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
    123     }
    124     Configuration configuration = this.properties.getConfiguration();
    125     if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
    126       configuration = new Configuration();
    127     }
    128     if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
    129       for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
    130         customizer.customize(configuration);
    131       }
    132     }
    133     factory.setConfiguration(configuration);
    134     if (this.properties.getConfigurationProperties() != null) {
    135       factory.setConfigurationProperties(this.properties.getConfigurationProperties());
    136     }
    137     if (!ObjectUtils.isEmpty(this.interceptors)) {
    138       factory.setPlugins(this.interceptors);
    139     }
    140     if (this.databaseIdProvider != null) {
    141       factory.setDatabaseIdProvider(this.databaseIdProvider);
    142     }
    143     if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
    144       factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
    145     }
    146     if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
    147       factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
    148     }
    149     if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
    150       factory.setMapperLocations(this.properties.resolveMapperLocations());
    151     }
    152 
    153     return factory.getObject();
    154   }
    155 
    156   @Bean
    157   @ConditionalOnMissingBean
    158   public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    159     ExecutorType executorType = this.properties.getExecutorType();
    160     if (executorType != null) {
    161       return new SqlSessionTemplate(sqlSessionFactory, executorType);
    162     } else {
    163       return new SqlSessionTemplate(sqlSessionFactory);
    164     }
    165   }
    238 }

    3、MybatisAutoConfiguration:

    ①类中有个MybatisProperties类,该类对应的是mybatis的配置文件

    ②类中有个sqlSessionFactory方法,作用是创建SqlSessionFactory类、Configuration类(mybatis最主要的类,保存着与mybatis相关的东西)

    ③SelSessionTemplate,作用是与mapperProoxy代理类有关

    4、关注下Configuration中的MapperRegister类,该类是创建dao(mapper的代理类),后续具体执行dao查询操作的都是基于该类的

    下边是springboot项目启动栈信息:

    1、springboot启动调用SpringApplication的静态方法run

      

    2、进入run方法:先进行springboot相关初始化

      

    3、进入refreshContext方法:初始化springboot的上下文

    4、进入refresh方法(AbstractApplicationContext)

    5、通过beanfactory实力各种bean

    。。。。

    6、在ConfigurationClassBeanDefinitionReader类来注册加载所有的spring.facotrys中指定的类

    7、最后到MybatisAutoConfiguration的registerBeanDefinition方法中,并且在new classPathMapperScanner对象中会配置environment

    8、通过ClassPathMapperScanner扫描mapper文件

    9、进入scanner的doscan方法(其实调用的是父类的doScan方法)

     10、进入父类ClassPathBeanDefinitionScanner类的doScan方法(其中basePackages就是application的包路径,这个包路径其实就是@springBootApplication注解中的一个主机ComponentScan类得到的)

    11、在findCandidateComponents中返回Set集合(mapper类的集合)

    。。。。

    12、当springboot调用getBean方法是才是真正创建类的时候

    13、最终到创建MybatisAutoConfiguration类了

    在创建之前会调用checkConfigFileExists方法(因为方法上有@PostConstruct),校验mybatis配置文件是否存在

    14、以上校验完之后,到注入属性

      注入的时候通过beanname调用getbean方法来获取一个bean

    15、在doGetBean方法中通过getSigngton(name)方法来获取已经注册过得bean,注册的bean都存在DefaultSingletonBeanRegister类的SingtonObjects的map对象中

     

    另外该map对象中还存了这些bean:

      SqlsessionFactory:

      

      与事务相关的bean:

      

      环境变量:

      

      数据源配置bean:

      

      sqlSessionTemplate:

      

      等等。。。。

    16、getbean最终通过MapperFactoryBean中的getObject方法来获取,其中getSqlSession方法返回的是SqlSessionTemplate,也就是getMapper调用的是SQLSessionTemplate中

    的方法

    17、进去到SqlSessionTemplage,getMapper实际上是从Configuration对象中类获取mapper

    18、进去到Configuration中,getMapper实际上是从MapperRegister对象中获取的

    19、进入到MapperRegister中,getMapper是从knownMappers 的map对象中来获取的,获取到mapperProxyFactory后,mapper工厂通过newInstance来创建一个mapperProxy

    代理对象

     

    20、这个mapperProxy就是在使用userdao的时候的代理类

  • 相关阅读:
    GMS问题_ThemeHostTest#testThemes
    解压system.img
    Android10_原理机制系列_AMS(ATMS)之应用的第一次启动的过程
    Android10_原理机制系列_AMS之AMS的启动
    如何用云开发高效快捷地实现短信验证码登录?
    推荐一款强大的前端CLI命令行工具
    CloudBase Framework丨第一个 Deno 部署工具是如何打造的?
    实战 | 打造一个双端自动发布的博客体系(下)
    从java注解漫谈到typescript装饰器——注解与装饰器
    TS数据类型:从C++/Java/Python到TS看元组tuple—元组的来龙去脉
  • 原文地址:https://www.cnblogs.com/nxzblogs/p/10484281.html
Copyright © 2011-2022 走看看