(三) mybatis 源码之 SqlSession

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);
       }
     } 

猜你喜欢

转载自blog.csdn.net/Gp_2512212842/article/details/107653324