源码解析:mybatis调用链之获取sqlSession
SqlSession
通过SqlSession sqlSession = sqlSessionFactory.openSession();获取SqlSession实例,
DefaultSqlSessionFactory
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
//从数据源获取数据库连接
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//获取mybatis配置文件中的environment对象
final Environment environment = configuration.getEnvironment();
//从environment获取transactionFactory对象
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//创建事务对象
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//根据配置创建executor
final Executor executor = configuration.newExecutor(tx, execType);
//创建DefaultSqlSession
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();
}
}
openSessionFromDataSource主要分为一下几个步骤:
1、获取mybatis配置文件中的environment对象
final Environment environment = configuration.getEnvironment();
2、从environment获取transactionFactory对象
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
3、创建事务对象
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
这里以JdbcTransactionFactory(TransactionFactory实现类)为例,获取JdbcTransaction(Transaction实现类)
JdbcTransactionFactory
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
return new JdbcTransaction(ds, level, autoCommit);
}
4、创建Executor对象
Configuration
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
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);
}
//如果有<cache>节点,通过装饰器,添加二级缓存的能力
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
//通过interceptorChain遍历所有的插件为executor增强,添加插件的功能
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
1)调用Configuration对象方法newExecutor进行创建,根据executorType选择相应的Executor实现类,这里以选择默认的SIMPLE为例,则选择新建SimpleExecutor对象。
2)判断全局的cacheEnabled值(默认为true),通过装饰器,添加二级缓存的能力。因此,二级缓存配置需要在mybatis-config.xml的cache进行开启。另外从这里,可以看到若是cacheEnabled为false,则executor并未增加二级缓存的能力,表明二级缓存不能使用。
3)通过InterceptorChain的pluginAll方法遍历所有的插件为executor增强,添加插件的功能
InterceptorChain
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
ThresholdInterceptor一个Interceptor接口的自定义实现类
ThresholdInterceptor
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
Plugin类wrap方法,实现InvocationHandler,Interceptor的代理类。在wrap方法中,可以看到,会根据@Intercepts的信息以及目标对象的信息,判断是否需要对该对象进行拦截代理。
Plugin
//静态方法,用于帮助Interceptor生成动态代理
public static Object wrap(Object target, Interceptor interceptor) {
//解析Interceptor上@Intercepts注解得到的signature信息
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();//获取目标对象的类型
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);//获取目标对象实现的接口(拦截器可以拦截4大对象实现的接口)
if (interfaces.length > 0) {
//使用jdk的方式创建动态代理
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
注意:Configuration对象中保存有默认的executorType:ExecutorType defaultExecutorType = ExecutorType.SIMPLE;BatchExecutor、ReuseExecutor、SimpleExecutor都继承于BaseExecutor抽象类,BaseExecutor主要用于为一些基础属性如configuration、transaction等赋初始值。
5、创建DefaultSqlSession,获取sqlSession完成。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!