MyBatis源码笔记(一) -- 大致流程

测试代码如下:

//获得资源文件流mybatis-config.xml
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
//创建一个SqlSession
SqlSession sqlSession = sessionFactory.openSession();
//获得接口代理类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.xxxx;//开始调用

1 创建SqlSessionFactory

1.1 加载配置文件

SqlSessionFactoryBuilder类

public SqlSessionFactory build(Reader reader) {
   	return build(reader, null, null);
}

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      return build(parser.parse());
    } catch...
	 finally {
      ...
        reader.close();
      ...
    }
}

XMLConfigBuilder类

public XMLConfigBuilder(Reader reader, String environment, Properties props) {
	//构造一个需要验证,XMLMapperEntityResolver的XPathParser
  	this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
}

public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
   commonConstructor(validation, variables, entityResolver);
	//加载XML文件为document对象
   this.document = createDocument(new InputSource(inputStream));
}

XMLMapperEntityResolver主要用于避免联网获取验证文件

上面调用了重载的构造函数

private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    //首先调用父类初始化Configuration
    super(new Configuration());
    //错误上下文设置成SQL Mapper Configuration(XML文件配置),以便后面出错了报错用吧
    ErrorContext.instance().resource("SQL Mapper Configuration");
    //将Properties全部设置到Configuration里面去
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
 }

Configuration类是所有配置的装载类,贯穿mybatis的执行流程

1.2 解析配置文件

回顾下上面,在创建好XMLConfigBuilder后就要进行解析:

	XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
	return build(parser.parse());

XMLConfigBuilder类

public Configuration parse() {
    //如果已经解析过了,报错
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    //根节点是configuration
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
}

private void parseConfiguration(XNode root) {
   try {
      //分步骤解析
      //issue #117 read properties first
      //1.properties
      propertiesElement(root.evalNode("properties"));
      //2.类型别名
      typeAliasesElement(root.evalNode("typeAliases"));
      //3.插件
      pluginElement(root.evalNode("plugins"));
      //4.对象工厂
      objectFactoryElement(root.evalNode("objectFactory"));
      //5.对象包装工厂
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      //6.设置
      settingsElement(root.evalNode("settings"));
      // read it after objectFactory and objectWrapperFactory issue #631
      //7.环境
      environmentsElement(root.evalNode("environments"));
      //8.databaseIdProvider
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      //9.类型处理器
      typeHandlerElement(root.evalNode("typeHandlers"));
      //10.映射器
      mapperElement(root.evalNode("mappers"));
    } catch...
}

最终解析结果都会放进Configuration对象里,最终返回给上一层

1.3 创建SqlSessionFactory实例

public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
}

可以看到返回的是DefaultSqlSessionFactory

2 创建SqlSession

DefaultSqlSessionFactory类

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

可以看到最后返回的是DefaultSqlSession实例。

3 获取接口代理类

DefaultSqlSession类

public <T> T getMapper(Class<T> type) {
    //最后会去调用MapperRegistry.getMapper
    return configuration.<T>getMapper(type, this);
}

Configuration类

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
}

MapperRegistry类

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw...
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch...
}

最终是通过Configuration中的MapperRegistry成员根据指定class获取MapperProxyFactory这个工厂类来实例出一个代理类,MapperRegistry在解析XML配置文件的时候就会把需要代理的接口包装成MapperProxyFactory缓存起来。

最后附上网上的一张结构图
Mybatis Frame

猜你喜欢

转载自blog.csdn.net/seasonLai/article/details/82842298