这里不再详细展开Mybatis在SpringFramework集成时的配置。
主要针对Mybatis-Spring核心类的剖析,以及Mybatis在SpringBoot中的拆箱即用。
在前面的Mybatis生命周期-初始化过程中,提到:SqlSessionFactoryBuilder会通过XMLConfigBuilder
等对象读取mybatis-config.xml配置文件以及映射配置信息,进而得到Configuration 对象,然后创建SqlSessionFactory 对象。
而在Mybatis-Spring中,SqlSessionFactoryBean取代了SqlSessionFactoryBuilder,进行SqlSessionFactory对象的生成。
这里对上述相关类,进行阐述:
SqlSessionFactoryBean:Mybatis-Spring集成中,Spring初始化Mybatis的核心
FactoryBean<>:声明该类为一个工厂类
InitializingBean:利用Spring的生命周期接口,进行Mybatis对应Bean注入时间的时机控制(在配置注入完毕后)。详见
ApplicationListener<>:通过Spring下ApplicationContext的扩展能力,确保在上下文发生变化时,进行Mybatis配置的更新(主要针对Statement)。详见
SqlSessionFactoryBuilder:SqlSessionFactoryBean通过组合&委托的方式,调用SqlSessionFactoryBuilder,从而构建SqlSessionFactory。
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> { private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class); private Resource configLocation; private Configuration configuration; private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //EnvironmentAware requires spring 3.1 private String environment = SqlSessionFactoryBean.class.getSimpleName(); // 是否采取快速失败,用于在上下文刷新时,进行statement刷新 private boolean failFast; // Mybatis插件 private Interceptor[] plugins; // 其他Mybatis-Configuration的字段(略) // 各字段的getter/setter方法(略) /** * 核心方法,由Spring的生命周期进行控制(钩子函数-配置设置后,进行触发) * 进行数据校验,然后调用构建方法-buildSqlSessionFactory() */ @Override public void afterPropertiesSet() throws Exception { notNull(dataSource, "Property 'dataSource' is required"); notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required"); state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null), "Property 'configuration' and 'configLocation' can not specified with together"); this.sqlSessionFactory = buildSqlSessionFactory(); } /** * */ protected SqlSessionFactory buildSqlSessionFactory() throws IOException { Configuration configuration; XMLConfigBuilder xmlConfigBuilder = null; // 各条件分支,对configuration进行配置的载入,以及不同级别日志的输出 // 略 // 委托给SqlSessionFactoryBuilder,进行实际的SqlSessionFactory的构建。后续流程就和Mybatis生命周期-初始化流程一致。详见前文Mybatis生命周期-初始化流程 return this.sqlSessionFactoryBuilder.build(configuration); } /** * {@inheritDoc} */ @Override public SqlSessionFactory getObject() throws Exception { if (this.sqlSessionFactory == null) { afterPropertiesSet(); } return this.sqlSessionFactory; } @Override public Class<? extends SqlSessionFactory> getObjectType() { return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass(); } @Override public boolean isSingleton() { return true; } @Override public void onApplicationEvent(ApplicationEvent event) { if (failFast && event instanceof ContextRefreshedEvent) { // fail-fast -> check all statements are completed this.sqlSessionFactory.getConfiguration().getMappedStatementNames(); } } } b.SpringManagedTransaction有关Spring下Mybatis的事务,已经在Mybatis的事务模块,说明了。这里不再赘述。
提醒一下,只有在配置中未指定Mybatis事务管理,Spring才会采用默认事务管理-SpringManagedTransaction。
SqlSessionTemplate实现了SqlSession接口,代替Mybatis原有的DefaultSqlSession,完成指定的数据库操作。
private final SqlSession sqlSessionProxy; public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); } @Override public <T> T selectOne(String statement) { return this.sqlSessionProxy.<T> selectOne(statement); } // 其他略