MyBatis 源码分析-02-生成实例MapperProxy 代理对象

说明:

version :

  • MyBatis : 3.5.5

  • 项目地址 :MyBatis-source-learn

    image-20210325150307186

示例代码:

  • createSqlSession.java
public static void main(String[] args) {

    DataSource dataSource = getDataSource();
    TransactionFactory transactionFactory = new JdbcTransactionFactory();
    Environment environment = new Environment("development",  transactionFactory, dataSource);
     Configuration configuration = new Configuration(environment);
    configuration.addMapper(BlogMapper.class);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    Blog blog = mapper.selectBlog(1);
    System.out.println(blog);
}

源码分析:

  • 解析 获取SqlSession的过程:
  • SqlSession sqlSession = sqlSessionFactory.openSession();
    image-20210325150307186

调用过程:

1. SqlSession sqlSession = sqlSessionFactory.openSession();
2. DefaultSqlSessionFactory.openSession();
   2.1 DefaultSqlSessionFactory.openSessionFromDataSource();
      	  2.1.1 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
		  2.1.2 final Executor executor = configuration.newExecutor(tx, execType);//2. 创建执行器executor
		  2.1.3	return new DefaultSqlSession(configuration, executor, autoCommit);//3. 创建SqlSession

获取SqlSession过程

DefaultSqlSessionFactory .java

  @Override
  public SqlSession openSession() {
      
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }


/*
1. 获取 事务
*/
 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
     // 1. 获取事务
     Transaction tx = null;
    try {
        // environment : app 当前所处的阶段,开发或者测试, 或者发行阶段
      final Environment environment = configuration.getEnvironment();
       // 1.1  获取事务工厂 ,默认JDBC(JDBC,Spring,Managed(ibatis))
        final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
       // 1.2 创建事务
        tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
        //1.3 新建执行器 executor 
        //Executor type: SIMPLE(default), REUSE, BATCH
      final Executor executor = configuration.newExecutor(tx, execType);
        // 2. 创建 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();
    }
  }

解释步骤 获取执行器

  • Configuration.java
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) {
       // cacheEnabled =true ,默认值不修改的话,一定会走这一步的
     executor = new CachingExecutor(executor);
   }
   executor = (Executor) interceptorChain.pluginAll(executor);
   return executor;
 }

生成MapperProxy(代理对象)过程:

BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
  • DefaultSqlSession.java
@Override
 public <T> T getMapper(Class<T> type) {
   return configuration.getMapper(type, this);
 }
  • Configuration.java

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
   return mapperRegistry.getMapper(type, sqlSession);
 }
  • MapperRegisty.java
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
  if (mapperProxyFactory == null) {
    throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
  }
  try {
      // . 创建实例
    return mapperProxyFactory.newInstance(sqlSession);
  } catch (Exception e) {
    throw new BindingException("Error getting mapper instance. Cause: " + e, e);
  }
}
  • MapperProxyFactory.java
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
    // 返回实例 ,java.lang.reflect 包下的类
  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);
}

总结:

  1. MyBatis 生成实例是通过 Jdk 的proxy 方式生成, 当然也可以采用 cglib 的方式来生成实例对象.
  2. MyBatis 中Executor 中默认采用委托(装饰器模式, ) CachingExecutor的方式实现

参考:

  • https://MyBatis.org/MyBatis-3/zh/