简要分析SqlSessionFactoryBean类

119 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情

前言

SqlSessionFactoryBean作为Mybatis中一个特别重要的类,在Spring集成Mybatis框架发挥了重要作用,我们很有必要写一篇文章来简要分析一下它都做了啥操作;

实现的接口

SqlSessionFactoryBean中分别实现了三个接口:

1.FactoryBean<SqlSessionFactory>接口,表明SqlSessionFactoryBean用来生产SqlSessionFactory实例,主要方法看getObject()

2.InitializingBean接口,这是一个初始化功能,关键方法看afterPropertiesSet()

3.ApplicationListener<ApplicationEvent>接口,说明这是一个监听器,关注方法onApplicationEvent()

上面三个接口,我们重点看第二个InitializingBean接口,因为第一个接口和第三个接口的方法实现都特别简单:

   public SqlSessionFactory getObject() throws Exception {
       if (this.sqlSessionFactory == null) {
           this.afterPropertiesSet();
      }
​
       return this.sqlSessionFactory;
  }

第一个接口直接返回sqlSessionFactory

  public void onApplicationEvent(ApplicationEvent event) {
       if (this.failFast && event instanceof ContextRefreshedEvent) {
           this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
      }
  }

第三个接口事件监听做的事情基本可以不用管;所以下面剩下的就是第二个接口的处理逻辑了:

   public void afterPropertiesSet() throws Exception {
       Assert.notNull(this.dataSource, "Property 'dataSource' is required");
       Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
       Assert.state(this.configuration == null && this.configLocation == null || this.configuration == null || this.configLocation == null"Property 'configuration' and 'configLocation' can not specified with together");
       this.sqlSessionFactory = this.buildSqlSessionFactory();
  }

看代码就可以知道,afterPropertiesSet()方法只做了一件事情,那就是创建SqlSessionFactory;所有的创建逻辑全部都在buildSqlSessionFactory()方法中,创建出来的SqlSessionFactory后面通过第一个接口的getObject()方法返回给Spring IOC容器管理;

   final Configuration targetConfiguration;
​
   XMLConfigBuilder xmlConfigBuilder = null;
   // 如果configuration不为空,那么targetConfiguration由configuration赋值
   if (this.configuration != null) {
     targetConfiguration = this.configuration;
     if (targetConfiguration.getVariables() == null) {
       targetConfiguration.setVariables(this.configurationProperties);
    } else if (this.configurationProperties != null) {
       targetConfiguration.getVariables().putAll(this.configurationProperties);
    }
     // 如果指定来mybatis的配置文件,那么targetConfiguration值来自于xml配置
  } else if (this.configLocation != null) {
     xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), nullthis.configurationProperties);
     targetConfiguration = xmlConfigBuilder.getConfiguration();
  } else {
     LOGGER.debug(
        () -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
     // 否则就自己创建Configuration;
     targetConfiguration = new Configuration();
     Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
  }

上面的代码说明了SqlSessionFactoryBean中的配置可以是两个来源,一个是通过Spring的方式自己配置configuration,另一个就是直接通过configLocation配置mybatisxml配置文件;

   Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
   Optional.ofNullable(this.objectWrapperFactory).ifPresent(targetConfiguration::setObjectWrapperFactory);
   Optional.ofNullable(this.vfs).ifPresent(targetConfiguration::setVfsImpl);
​

接下来就处理一些简单的属性,比如objectFactoryobjectWrapperFactoryvfs等等;直至所有属性处理完毕,最后调用下面的build()方法完成SqlSessionFactory的构建:

this.sqlSessionFactoryBuilder.build(targetConfiguration);

小结

通过上述源码的分析,我们现在明白了SqlSessionFactoryBean其实就做了一件事情,那就是创建SqlSessionFactory;但是在创建SqlSessionFactory之前,其实是花了很大篇幅在处理targetConfiguration配置的,最终通过处理好的targetConfiguration构建出了sqlSessionFactory