openSession
SqlSession 用于与数据库进行一次会话, 需要从 SqlSessionFactory 中获取, 查看其 openSession 方法
// 一路调用来到这个方法
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
// 事务管理
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建执行器, 共有三种类型可选
final Executor executor = configuration.newExecutor(tx, execType);
// 封装到 SqlSession 对象中
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();
}
}
Executor
执行器, 四大对象之一, 有三种可选
public enum ExecutorType {
// 分别对应三种模式 : 普通, 复用, 批量
SIMPLE, REUSE, BATCH
}
在 Configuration 创建执行器的时候, 会被拦截器拦截, 所以可以实现 Interceptor 接口拓展 mybatis
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);
}
if (cacheEnabled) {
// 缓存
executor = new CachingExecutor(executor);
}
// 拦截器, 应用插件
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
最后将事务管理器, 执行器封装到 SqlSession 中
SqlSession
SqlSession 用于与数据库进行一次会话, 需要从 SqlSessionFactory 中获取, 查看其 openSession 方法
// SqlSessionFactory#openSession()
// 一路调用来到这个方法
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
// 事务管理
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建执行器, 共有三种类型可选
final Executor executor = configuration.newExecutor(tx, execType);
// 封装到 SqlSession 对象中
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();
}
}
Executor
执行器, 有三种可选
public enum ExecutorType {
// 分别对应三种模式 : 普通, 复用, 批量
SIMPLE, REUSE, BATCH
}
在 Configuration 创建执行器的时候, 会被拦截器拦截, 所以可以实现 Interceptor 接口拓展 mybatis
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);
}
if (cacheEnabled) {
// 缓存
executor = new CachingExecutor(executor);
}
// 拦截器, 应用插件
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
最后将 TransactionFactory , Executor 封装到 SqlSession 中
动态代理
// 一路调用来到 MapperProxyFactory 这个方法,
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),
new Class[]{mapperInterface}, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
mybatis 使用了 JDK 动态代理为接口实现了一个代理对象, (由 MapperProxyFactory 实现代理) , 交给 MapperProxy (实现了 InvocationHandler 接口) 拦截
public class MapperProxy<T> implements InvocationHandler, Serializable {
.....
private static final Method privateLookupInMethod;
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
private final Map<Method, MapperMethodInvoker> methodCache;
.....
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 该方法是 Object 中声明的方法 (equals, hashCode...), 直接执行
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
else {
// 交给 MapperMethodInvoker 调用, 其实最后还是交给 MappedMethod 调用
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
}
catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}