SqlSessionFactoryBean
继承FactoryBean接口,表示该类为创建SqlSessionFactory的工厂类
继承InitializingBean接口,在创建对象实例填充属性后会执行初始化回调,调用afterPropertiesSet方法完成mybatis的初始化(创建Configuration、Environment、MappedStatement····)
继承ApplicationListener接口,监听ApplicationEvent事件,确保mappedStatements解析完成
public class SqlSessionFactoryBean
implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
// 创建者,用来创建SqlSessionFactory,全局唯一
private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 配置文件
private Resource configLocation;
// xml资源位置
private Resource[] mapperLocations;
// 连接源
private DataSource dataSource;
}
MapperScannerConfigurer
mybatis中为mapper接口扫描生成代理类的配置类
继承BeanDefinitionRegistryPostProcessor接口,在初始化IOC容器时调用其postProcessBeanDefinitionRegistry方法
使用ClassPathMapperScanner扫描包中接口类,默认的include过滤器接受所有类,将包中接口类定义为BeanDifinition添加到当前beanFactory中
1.创建ScannedGenericBeanDefinition过滤掉不是接口的类metadata存放接口的原始信息,此时存在beanClass和resource
2.设置scope,处理注解来设置对应属性(Lazy、Primary、DependsOn、Role、Description),注册到BeanFactory中
3.设置BeanDifinition的属性,核心为设置beanClass为mapperFactoryBean(所有接口类都为该类型),配置sqlSessionFactory、sqlSessionTemplate属性值
继承InitializingBean接口,确保basePackage不为null
public class MapperScannerConfigurer
implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
// 扫描包位置
private String basePackage;
// 持有的SqlSessionFactory
private SqlSessionFactory sqlSessionFactory;
private SqlSessionTemplate sqlSessionTemplate;
// SqlSessionFactory的Bean名称
private String sqlSessionFactoryBeanName;
private String sqlSessionTemplateBeanName;
// SqlSession代理对象生成
private Class<? extends MapperFactoryBean> mapperFactoryBeanClass;
}
MapperFactoryBean
继承结构
继承FactoryBean接口,生成代理Mapper对象,@AutoWired通过DefaultListableBeanFactory的resolveDependency方法解析,在findAutowireCandidates方法时
调用了createInstance方法创建接口实例,并放入factoryBeanInstanceCache中
继承InitializingBean接口,确保Configuration类中mapperRegistry已经加载对应的Mapper接口
mapperInterface通过构造函数传入
通过传入SqlSessionFactory创建SqlSessionTemplate
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
// 真实Mapper接口
private Class<T> mapperInterface;
// 是否将Mapper添加到配置
private boolean addToConfig = true;
}
SqlSessionTemplate
通过SqlSessionInterceptor拦截,每次调用时生成一个DefaultsqlSession来执行方法,保证线程安全。
public class SqlSessionTemplate implements SqlSession, DisposableBean {
// 工厂 required
private final SqlSessionFactory sqlSessionFactory;
// 执行器类型 required
private final ExecutorType executorType;
// sqlSession代理
private final SqlSession sqlSessionProxy;
// 构造方法
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());
}
}
// 代理方法
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 通过事务同步管理器来获得sqlSession,如果未开启事务则每次获得新的sqlSession
SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
try {
// 新的sqlSession来处理
Object result = method.invoke(sqlSession, args);
// 未开启事务自动提交
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// release the connection to avoid a deadlock if the translator is no loaded. See issue #22
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
sqlSession = null;
Throwable translated = SqlSessionTemplate.this.exceptionTranslator
.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
// 关闭sqlSession
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}