mybatis-spring 基于xml配置原理介绍
2020-07-26 本文已影响0人
晴天哥_王志
系列
- mybatis-3.4.6 配置介绍
- mybatis-3.4.6 顶层配置解析
- mybatis-3.4.6 子配置解析
- mybatis-3.4.6 mapper解析
- mybatis-3.4.6 SQL执行流程
- mybatis-3.4.6 SqlSession执行过程
- mybatis-3.4.6 缓存介绍
- mybatis-3.4.6 自增主键
- mybatis-3.4.6 foreach 自增主键
- mybatis-3.4.6 事务管理
- mybatis-spring 基于xml配置原理介绍
开篇
- 这个系列是基于mybatis-3.4.6版本的源码解析,这篇文章主要用于分析mybatis和spring的整合逻辑。
- mybatis-spring是再mybatis的继承上进行了二次封装,所以核心依旧得理解mybatis。
核心逻辑
SqlSessionTemplatepublic 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的执行逻辑了。