前言:在MyBatis源码解析(二):初始化SqlSessionFactory中,已经成功解析XML配置文件,并初始化SqlSessionFactory;这一篇将对 SqlSessionFactory.openSession() 进行解析
一,SqlSessionFactory.openSession() 执行流程
二,初始化步骤
1,触发 openSession(),内部调用 openSessionFromDataSource() 完成初始化动作
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
// 从Configuration中获取Environment配置信息
final Environment environment = configuration.getEnvironment();
// 从Environment配置信息获取事务工厂
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 初始化事务, 此时事务持有dataSource对象
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 初始化Executor, Executor通过Transaction间接持有DataSource对象
final Executor executor = configuration.newExecutor(tx, execType);
// 初始化SqlSession对象, SqlSession持有configuration和executor引用
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
2,初始化数据库事务 -- JdbcTransactionFactory.newTransaction
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
// 此时数据库事务持有DataSource信息
return new JdbcTransaction(ds, level, autoCommit);
}
3,初始化 Executor 执行对象 -- Configuration.newExecutor
* ExecuteType配置信息和CacheEnabled配置信息官网解释
* 初始化Executor方法;在开启缓存处理的情况下,注意此处通过装饰者模式对 SimpleExecutor 进行了二次装饰 CachingExecutor
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
// executorType如果未配置, 默认为Simple
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
// 未配置默认开启
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
// 通过拦截器加载plugin, 返回对象为代理对象
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
* Executor 初始化时, 关联加载 Plugin 插件,并生成Executor代理对象,此处注意:代理对象可以被再次代理
public Object pluginAll(Object target) {
// 此处遍历Plugins标签内所有Plugin进行加载
// 通过代理对象再代理模式, 保证每一个拦截器都能被执行
// 此处注意点 : 代理对象可以被再次代理
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
* 生成 Executor 对象的代理对象,如存在多个,则后续传入的对象已经是代理对象,类似装饰者模式方式
public static Object wrap(Object target, Interceptor interceptor) {
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
// 存在有效插件
if (interfaces.length > 0) {
// 对target即executor进行代理
// 外部循环调用, 则此时executor对象可能已经是代理对象
// 允许对代理对象再次进行代理
// 最终执行时, 装箱代理, 拆箱调用, 类似装饰者模式一层层进行处理
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
4,初始化SqlSession成功,获取的 SqlSession 为 DefaultSqlSession,此时 SqlSession 持有配置对象 Configuration,执行对象 CachingExecetor,已经持有 DataSource 配置的数据库事务对象 Transaction
SqlSession sqlSession = sqlSessionFactory.openSession();