您当前的位置: 首页 >  sql

white camel

暂无认证

  • 0浏览

    0关注

    442博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

MyBatis运行原理(二) : 获取SqlSession的流程、getMapper获取接口代理对象流程 (源码分析)

white camel 发布时间:2021-04-22 11:44:56 ,浏览量:0

二、获取SqlSession的流程

在这里插入图片描述 1、进入到openSession()方法, 因为sqlSessionFactory在运行时的对象为DefaultSqlSessionFactory, 所以通过动态绑定机制调用的openSession为DefaultSqlSessionFactory的

  @Override
  public SqlSession openSession(boolean autoCommit) {
  	// configuration.getDefaultExecutorType() 为默认的SIMPLE类型的执行器
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
  }

2、进入到DefaultSqlSessionFactory类的openSessionFromDataSource方法中

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);
      // 创建Executor执行器对象
      final Executor executor = configuration.newExecutor(tx, execType);
      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();
    }
  }

3、进入Configuration类的newExecutor(tx, execType)方法

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    // 此处根据全局配置文件中配置的ExecutorType的类型, 来创建不同的XxxExecutor
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      // 默认是SIMPLE类型, 所以创建SimpleExecutor对象
      executor = new SimpleExecutor(this, transaction);
    }
    // 如果有二级缓存, 就会创建CachingExecutor对象
    /*
    	该对象内部调用的查询方法对象, 实际还是传进去的executor
    */
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

public enum ExecutorType {
  // BATCH为批量执行器
  SIMPLE, REUSE, BATCH
}

Executor : 每一个SqlSession都会拥有一个Executor对象,这个对象负责增删改查的具体操作,我们可以简单的将它理解为JDBC中Statement的封装版。 在这里插入图片描述 在这里插入图片描述

4、进入CachingExecutor看一下

public class CachingExecutor implements Executor {

  private final Executor delegate;
  private final TransactionalCacheManager tcm = new TransactionalCacheManager();

  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    delegate.setExecutorWrapper(this);
  }
  
  // 省略...
  
  @Override
  public  List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    Cache cache = ms.getCache();
    if (cache != null) {
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, boundSql);
        @SuppressWarnings("unchecked")
        List list = (List) tcm.getObject(cache, key);
        if (list == null) {
          // 使用的仍然是传进来的executor
          list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
	// 使用的仍然是通过构造器传进来的executor
    return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

5、newExecutor方法最终返回的executor对象都要走InterceptorChain类的pluginAll方法, 来将executor对象通过每个拦截器包装一下, 并返回最终的executor

executor = (Executor) interceptorChain.pluginAll(executor);

public Object pluginAll(Object target) {
  for (Interceptor interceptor : interceptors) {
    target = interceptor.plugin(target);
  }
  return target;
}

6、最终将这个包装好的executor对象, 传入到DefaultSqlSession中 在这里插入图片描述 7、最终调用的openSession()方法, 会返回一个DefaultSqlSession对象 在这里插入图片描述 1-7时序图如下:

总结: 返回的SqlSession的实现类DefaultSqlSession对象, 它包含了Executor和Configuration。Executor会在这一步被创建 在这里插入图片描述

在这里插入图片描述

三、getMapper获取接口的代理对象

在这里插入图片描述 1、进入DefaultSqlSession类的getMapper(Class class)方法

// 进入到DefaultSqlSession的getMapper方法
  @Override
  public  T getMapper(Class type) {
  	// 调用configuration的getMapper
    return configuration.getMapper(type, this);
  }

// 进入到Configuration的getMapper方法
  public  T getMapper(Class type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

2、进入到MapperRegistry类的getMapper方法

  public  T getMapper(Class type, SqlSession sqlSession) {
  	// 直接从knownMappers拿到type的MapperProxy对象
    final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) 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);
    }
  }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述 3、进入mapperProxyFactory.newInstance(sqlSession)方法

// MapperProxyFactory类的方法
  public T newInstance(SqlSession sqlSession) {
    // 创建了MapperProxy对象
    // public class MapperProxy implements InvocationHandler, Serializable {}
    // 所以MapperProxy
    final MapperProxy mapperProxy = new MapperProxy(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

// 进入newInstance(MapperProxy proxy)方法
  // 创建MapperProxy代理对象
  protected T newInstance(MapperProxy mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

4、最终就创建了UserMapper接口的代理对象 在这里插入图片描述

时序图如下: 在这里插入图片描述

关注
打赏
1661428283
查看更多评论
立即登录/注册

微信扫码登录

0.0421s