MyBatis源码分析:SqlSession获取过程

public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //SqlSessionFactory初始化
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession
        SqlSession session = factory.openSession();

        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = userMapper.getUserById("1");
        System.out.println(user);

}

1、SqlSessionFactory初始化过程

//class:SqlSessionFactoryBuilder
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      //创建XML解析器来解析xml配置文件
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      //parser.parse()解析xml文件
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

  //返回包含了Configuration的DefaultSqlSession对象。
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
//把配置文件的信息解析并保存在Configuration对象中 
public Configuration parse() {
      //如果已经解析过了,抛出异常
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
      //配置文件的根节点是configuration
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

解析配置文件:

分步骤解析xml文件的各个节点

private void parseConfiguration(XNode root) {
    try {
      Properties settings = settingsAsPropertiess(root.evalNode("settings"));
      //issue #117 read properties first
      //解析properties
      propertiesElement(root.evalNode("properties"));
      //解析settings
      loadCustomVfs(settings);
      //解析typeAliases,类型别名
      typeAliasesElement(root.evalNode("typeAliases"));
      //解析插件
      pluginElement(root.evalNode("plugins"));
      //解析对象工厂
      objectFactoryElement(root.evalNode("objectFactory"));
      //解析对象包装工厂
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      //解析reflectorFactory
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      //把settings里各个所有设置设置到configruation上
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      //解析environments
      environmentsElement(root.evalNode("environments"));
      //解析databaseIdProvider
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      //解析typeHandlers,类型处理器
      typeHandlerElement(root.evalNode("typeHandlers"));
      //解析mappers
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

Mybatis会把配置文件的所有信息都保存在Configuration对象中,并返回包含了configuration的DefualtSqlSessionFactoryd对象
configuration对象:

这里写图片描述

主要过程:

​ 解析xml的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSessionFactory;

2、SqlSession获取

SqlSession session = factory.openSession();
  //class:DefaultSqlSessionFactory
  @Override
  public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }

  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);
      //构建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();
    }
  }

执行器Executor创建过程:

//根据传入的ExecutorType来构建不同的Executor,可以在配置文件中配置,默认是SIMPLE
//final Executor executor = configuration.newExecutor(tx, execType);
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);
    }
     //如果要求缓存,生成另一种CachingExecutor(默认就是有缓存),装饰者模式,所以默认都是返回CachingExecutor
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    //此处调用插件,通过插件可以改变Executor行为,采用的是责任链模式,来产生代理对象
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

SqlSession对象中包含configuration和executor
这里写图片描述

主要过程:

​ 1、根据ExecutorType创建Executor,默认是SIMPLE类型的,但因为cacheEnabled默认是为true的,所以实际上生成的是CachingExecutor,里面包含了一个Executor,使用了装饰者模式;

​ 2、返回一个DefaultSqlSession对象,该对象包含Configuration和Executor;

猜你喜欢

转载自blog.csdn.net/wangbing25307/article/details/81189824
今日推荐