MyBatis 源码解读(一)配置文件加载解析

MyBatis 是最喜欢的框架,他的灵活性、可扩展性目前来说是最实用的,与其同类型的框架或多或少都有一些几乎让人无法忍受的缺点,目前在 MyBatis 中还没有发现令笔者无法忍受的弊端。

MyBatis 是以 SQLSessionFactory 为中心进行构建的。SQLSessionFactory 的主要任务是创建 SQLSessionSQLSession 是实际数据库交互的核心部分。MyBatis 提供了两种模式去创建 SQLSessionFactory:一种是XML方式,这是笔者推荐的方式;另一种是代码的方式。能够使用配置文件的时候,我们要尽量的使用配置文件,这样一方面可以避免硬编码,一方面方便日后配置人员的修改,避免重复编译代码。

接下来将一点一点的解读 MyBatis,为了方便解读我们需要 首先 Fork MyBatis 的源码到我们自己的 Github 空间,还要创建一个用于测试的项目mybatis-learn

创建测试项目

在这里插入图片描述

入口 创建SQLSessionFactory

接下来我们深入剖析一下,SQLSessionFactory 是如何被构建的

public class SqlSessionFactoryTest {
  Logger logger = LoggerFactory.getLogger(SqlSessionFactoryTest.class) ;
  @Test
  public void testCreateSessionFactory() throws Exception {
    String  resource = "mybatis-config.xml" ;
    InputStream inputStream = Resources.getResourceAsStream(resource) ;
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream) ;
    logger.info(sqlSessionFactory.toString());
  }
}

在第7行代码SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream) ;中可以看到 SQLSessionFactory根据 mybatis-config.xml 完成了工厂类的构建。这个将是学习的入口。我们看一下实现代码

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    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.
    }
  }
}

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

通过第34行代码我们可以看见我们的配置信息通过 XMLCongfigBuilder对象的parse方法被解析成了Configuration类对象,这个类对象包含了各种配置项很重要,它将存在于整个MyBatis 的生命周期中,一遍重复读取和运用。

最终创建了一个 DefaultSqlSessionFactory 对象,在 MyBatis 中提供了两个SQLSessionFactory的实现类,DefaultSqlSessionFactorySqlSessionManager。不过SQLSessionManager目前还没有使用,MyBatis 中目前使用的是DefaultSqlSessionFactory。让我们看看他们的关系图
在这里插入图片描述

配置解析 XMLConfigBuilder.parseConfiguration(XNode root)

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

根据我们传入的参数我们最终通过 XMLConfigBuilder.parseConfiguration 将相关配置放到 Configuration 对象中,它将存在于整个MyBatis 的生命周期中,一遍重复读取和运用。

public Configuration parse() {
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
}

private void parseConfiguration(XNode root) {
  try {
    // issue #117 read properties first
    propertiesElement(root.evalNode("properties"));
    Properties settings = settingsAsProperties(root.evalNode("settings"));
    loadCustomVfs(settings);
    loadCustomLogImpl(settings);
    typeAliasesElement(root.evalNode("typeAliases"));
    pluginElement(root.evalNode("plugins"));
    objectFactoryElement(root.evalNode("objectFactory"));
    objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
    reflectorFactoryElement(root.evalNode("reflectorFactory"));
    settingsElement(settings);
    // read it after objectFactory and objectWrapperFactory issue #631
    environmentsElement(root.evalNode("environments"));
    databaseIdProviderElement(root.evalNode("databaseIdProvider"));
    typeHandlerElement(root.evalNode("typeHandlers"));
    mapperElement(root.evalNode("mappers"));
  } catch (Exception e) {
    throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  }
}

parseConfiguration(XNode root) XNode root 参数为将 mybatis-config.xml 对象解析后的对象,即我们的配置项。

解析配置的系统变量
propertiesElement(root.evalNode(“properties”));
 
Properties settings = settingsAsProperties(root.evalNode(“settings”));
解析配置的文件加载系统
loadCustomVfs(settings);
解析配置使用的日志系统
loadCustomLogImpl(settings);
解析配置的别名
typeAliasesElement(root.evalNode(“typeAliases”));
解析配置的插件
pluginElement(root.evalNode(“plugins”));
解析自定义对象工厂
objectFactoryElement(root.evalNode(“objectFactory”));
解析自定义对象封装工厂
objectWrapperFactoryElement(root.evalNode(“objectWrapperFactory”));
解析自定义反射工厂
reflectorFactoryElement(root.evalNode(“reflectorFactory”));
解析自定义系统设置项
settingsElement(settings);
读取数据库配置信息
environmentsElement(root.evalNode(“environments”));
设置当前使用数据库类型
databaseIdProviderElement(root.evalNode(“databaseIdProvider”));
设置自定义数据类型处理类
typeHandlerElement(root.evalNode(“typeHandlers”));
解析SQL配置文件
mapperElement(root.evalNode(“mappers”));*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值