美文网首页mybatis
mybatis-spring 基于xml配置原理介绍

mybatis-spring 基于xml配置原理介绍

作者: 晴天哥_王志 | 来源:发表于2020-07-26 19:19 被阅读0次

系列

开篇

  • 这个系列是基于mybatis-3.4.6版本的源码解析,这篇文章主要用于分析mybatis和spring的整合逻辑。
  • mybatis-spring是再mybatis的继承上进行了二次封装,所以核心依旧得理解mybatis。

核心逻辑

SqlSessionTemplate
public class SqlSessionTemplate implements SqlSession, DisposableBean 
  • SqlSessionTemplate是mybatis-spring的核心数据结构。
  • SqlSessionFactoryBean通过getObject返回DefaultSqlSessionFactory对象。
  • MapperFactoryBean通过getObject返回mapper可执行对象。
  • MapperFactoryBean的setSqlSessionFactory方法在注入DefaultSqlSessionFactory对象的时候会创建SqlSessionTemplate对象。

Demo

public interface UserMapper {
  @Select("SELECT * FROM users WHERE id = #{userId}")
  User getUser(@Param("userId") String userId);
} 

<! -- 开启事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <constructor-arg ref="dataSource" />
</bean>

<! -- 定义sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>

<! -- 定义DAO对象 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
  • 通过SqlSessionFactoryBean定义sqlSessionFactory对象。
  • 通过MapperFactoryBean定义Dao对象直接用于SQL查询。
  • SqlSessionFactoryBean和MapperFactoryBean的分析

SqlSessionFactoryBean

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}
  • FactoryBean通过getObject来生成bean对象,实现类SqlSessionFactoryBean重写了getObject来生成返回的bean对象。
public class SqlSessionFactoryBean
    implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {

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

    return this.sqlSessionFactory;
  }

  public void afterPropertiesSet() throws Exception {
    this.sqlSessionFactory = buildSqlSessionFactory();
  }


  protected SqlSessionFactory buildSqlSessionFactory() throws Exception {

    final Configuration targetConfiguration;

    XMLConfigBuilder xmlConfigBuilder = null;
    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);
      }
    } else if (this.configLocation != null) {
      xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
      targetConfiguration = xmlConfigBuilder.getConfiguration();
    } else {
      // 创建Configuration对象
      targetConfiguration = new Configuration();
      Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
    }

    // 省略相关代码

    if (this.mapperLocations != null) {
      if (this.mapperLocations.length == 0) {
      } else {
        for (Resource mapperLocation : this.mapperLocations) {
          try {
            // 通过XMLMapperBuilder来进行解析
            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
                targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
            // 通过parse将配置解析到Configuration对象当中
            xmlMapperBuilder.parse();
          } catch (Exception e) {
          } finally {
            ErrorContext.instance().reset();
          }
        }
      }
    } 

    // 返回DefaultSqlSessionFactory对象。
    return this.sqlSessionFactoryBuilder.build(targetConfiguration);
  }
}
  • SqlSessionFactoryBean的getObject的核心会执行afterPropertiesSet方法。
  • afterPropertiesSet方法的通过XMLMapperBuilder来解析mapper.xml文件生成Configuration对象。
  • sqlSessionFactoryBuilder.build调用mybatis的build方法返回mybatis的DefaultSqlSessionFactory对象。

MapperFactoryBean

SqlSessionDaoSupport

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {}

public abstract class SqlSessionDaoSupport extends DaoSupport {

  private SqlSessionTemplate sqlSessionTemplate;

  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
      this.sqlSessionTemplate = createSqlSessionTemplate(sqlSessionFactory);
    }
  }

  protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}
  • MapperFactoryBean继承自SqlSessionDaoSupport类。
  • SqlSessionDaoSupport的setSqlSessionFactory在设置对象的时候执行createSqlSessionTemplate来创建SqlSessionTemplate对象。
  • SqlSessionTemplate对象是mybatis-spring中最核心的执行SQL的对象

SqlSessionTemplate

public class SqlSessionTemplate implements SqlSession, DisposableBean {
  // sqlSessionFactory是DefaultSqlSessionFactory
  private final SqlSessionFactory sqlSessionFactory;
  private final ExecutorType executorType;
  private final SqlSession sqlSessionProxy;
  private final PersistenceExceptionTranslator exceptionTranslator;

  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {

    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class }, new SqlSessionInterceptor());
  }
}
  • SqlSessionTemplate的SqlSessionFactory注入的是SqlSessionFactoryBean返回的DefaultSqlSessionFactory对象。
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {

  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }
}


public abstract class SqlSessionDaoSupport extends DaoSupport {
  public SqlSession getSqlSession() {
    return this.sqlSessionTemplate;
  }
}
  • MapperFactoryBean的getObject方法返回mapper对象
  • MapperFactoryBean的getSqlSession()返回sqlSessionTemplate对象。
  • SqlSessionTemplate的getMapper()返回真正的mapper对象。
public class SqlSessionTemplate implements SqlSession, DisposableBean {
  // 注入的DefaultSqlSessionFactory对象
  private final SqlSessionFactory sqlSessionFactory;
  private final ExecutorType executorType;
  private final SqlSession sqlSessionProxy;
  private final PersistenceExceptionTranslator exceptionTranslator;

  public <T> T getMapper(Class<T> type) {
    return getConfiguration().getMapper(type, this);
  }

  public Configuration getConfiguration() {
    return this.sqlSessionFactory.getConfiguration();
  }
}
  • SqlSessionTemplate的getMapper最终执行的就是mybatis的Configuration对象的getMapper方法。
  • getMapper方法返回的就是mybatis的对象进而进入到mybatis的执行逻辑了。

参考文档

相关文章

网友评论

    本文标题:mybatis-spring 基于xml配置原理介绍

    本文链接:https://www.haomeiwen.com/subject/eutelktx.html