一、SqlSessionFactory 对象初始化

 //加载全局配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//1.获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

1.调用SqlSessionFactoryBuilder的build(inputStream);方法,方法如下:

public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }

实际上调用如下方法;

  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      //XMLConfigBuilder是对mybatis的配置文件进行解析的类
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      //1.调用当前类的parse() 方法,返回configuration。2.调用build方法,返回SqlSessionFactory
      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.
      }
    }
  }
  • 首先传入全局配置文件的输入流,创建了XMLConfigBuilder对象。然后调用XMLConfigBuilder 的parse()方法。代码如下:
  public Configuration parse() {
    //判断Configuration是否解析过,Configuration是全局变量,只需要解析创建一次即可
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    //调用下面的方法,parser.evalNode("/configuration")解析XML配置的configuration节点的内容,得到XNode对象
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

parser.evalNode(“/configuration”)是调用了XPathParser类的evalNode方法返回的是XNode对象。XNode对象保存了解析后的对应节点下的所有信息。

  • 然后parseConfiguration(parser.evalNode("/configuration")); 方法,代码如下:
 //根据root中存储的是configuration节点的内容
 private void parseConfiguration(XNode root) {
    try {
       //设置settings配置
      Properties settings = settingsAsPropertiess(root.evalNode("settings"));
       //设置properties配置
      propertiesElement(root.evalNode("properties"));
      loadCustomVfs(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"));
      //设置mappers配置
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

可以看出parse的作用是解析mybatis-config.xml的configuration节点的内容,然后挨个赋值给configuration对象的属性;

  • settingsElement(settings); 方法如下:将全局配置文件中所有结点的配置信息都设置到了configuration对象中
private void settingsElement(Properties props) throws Exception {
    configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
    configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
    configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
  • mapperElement(root.evalNode("mappers")); 方法,则是将是对SQL映射文件进行了解析。解析后将信息设置到了configuration对象中
  private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();

解析mapper映射文件代码如下:

 private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      builderAssistant.setCurrentNamespace(namespace);
      cacheRefElement(context.evalNode("cache-ref"));
      cacheElement(context.evalNode("cache"));
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      sqlElement(context.evalNodes("/mapper/sql"));
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
    }
  }

到这里 return build(parser.parse()); 就要返回了,build方法如下:

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

返回的SqlSessionFactory 对象中封装了所有的配置信息。Configuration封装了所有配置文件的详细信息。

总结:把配置文件的信息解析并保存在Configuration对象中,返回包含了Configuration的DefaultSqlSession对象。

MyBatis 3源码解析(一)的更多相关文章

  1. MyBatis详细源码解析(上篇)

    前言 我会一步一步带你剖析MyBatis这个经典的半ORM框架的源码! 我是使用Spring Boot + MyBatis的方式进行测试,但并未进行整合,还是使用最原始的方式. 项目结构 导入依赖: ...

  2. Mybatis SqlNode源码解析

    1.ForEachSqlNode mybatis的foreach标签可以将列表.数组中的元素拼接起来,中间可以指定分隔符separator <select id="getByUserI ...

  3. Mybatis SqlSessionTemplate 源码解析

    As you may already know, to use MyBatis with Spring you need at least an SqlSessionFactory and at le ...

  4. MyBatis 3源码解析(四)

    四.MyBatis 查询实现 Employee empById = mapper.getEmpById(1); 首先会调用MapperProxy的invoke方法 @Override public O ...

  5. MyBatis 3源码解析(三)

    三.getMapper获取接口的代理对象 1.先调用DefaultSqlSession的getMapper方法.代码如下: @Override public <T> T getMapper ...

  6. MyBatis 3源码解析(二)

    二.获取SqlSession对象 1.首先调用DefaultSqlSessionFactory 的 openSession 方法,代码如下: @Override public SqlSession o ...

  7. mybatis源码解析1--前言

    在开始分析mybatis源码之前,需要定一个目标,也就是我们不是为了读源码而去读,一定是带着问题去读,在读的时候去寻找到答案,然后再读码的同时整理总结,学习一些高级的编码方式和技巧. 首先我们知道my ...

  8. Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码

    在文章:Mybatis源码解析,一步一步从浅入深(一):创建准备工程,中我们为了解析mybatis源码创建了一个mybatis的简单工程(源码已上传github,链接在文章末尾),并实现了一个查询功能 ...

  9. Mybatis源码解析(一)(2015年06月11日)

    一.简介 先看看Mybatis的源码结构图,Mybatis3.2.7版本包含的包共计19个,其他版本可能会少. 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为 ...

随机推荐

  1. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  2. 为什么要抛弃Pact?如何快速实现契约测试(CDC)

    前言 在前几天的博客中,我转载了一篇文章,其中介绍了契约测试和pact是怎么实施的,的确很有帮助.但我经过研究,其实是pact本身也是有缺陷的,结合我近期在使用的服务型工具和我的实际情况,觉得实现契约 ...

  3. Tomcat 对 HTTP 协议的实现(上)

    协议,直白的说就是存在一堆字节,按照协议指定的规则解析就能得出这堆字节的意义.HTTP 解析分为两个部分:解析请求头和请求体. 请求头解析的难点在于它没有固定长度的头部,也不像其他协议那样提供数据包长 ...

  4. javascript小记一则:今天在写VS2005——.NET程序时,写的一个JS图片示例案例

    源码如下,如遇调试问题,可以找我解决: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  5. C#开发——网站应用微信登录开发

    1. 在微信开放平台注册开发者账号,并有一个审核已通过的网站应用,并获得相对应的AppID和AppSecret,申请通过登陆后,方可开始接入流程. 2.微信OAuth2.0授权登录目前支持author ...

  6. int 与 Integer 的区别

    int和Integer的区别 Integer是int的包装类,int则是java的一种基本数据类型 Integer变量必须实例化后才能使用,而int变量不需要 Integer实际是对象的引用,当new ...

  7. easyui表格排序

    效果:点击DataGrid表格某个头部,进行升序或降序排序当前页: 问题:对应列设置  sortable:true 没有效果,刚开始以为是对应的列对应的数据库的字段类型有问题, 改动代码,使返回到前台 ...

  8. android WebView技术笔记(存储技术)

    作为刚刚开始工作的新手程序猿,各种知识还不算熟练,所以将学习到的知识记录一下以免以后忘记. WebView加载h5的知识现在可以说非常的常用,通过加载h5的网页可以在不更新app的情况下来更新app的 ...

  9. android使用百度地图最新sdk5.0后后代码混淆时,地图无法显示闪退问题

    描述:刚开始遇到这个问题我一步一步去排除,最后发现在初始化地图的时候,代码混淆就有问题了, 问题描述:当跳显示地图的页面APP闪退, 解决对比: 1:对于老版本百度sdk:代码混淆时语句: -libr ...

  10. appium+python搭建自动化测试框架_TestAPP框架(三)

    Pycharm 创建 Project,搭建 APPTEST框架如下图:   1.框架功能 业务功能的封装 测试用例封装 测试包管理 截图处理 断言处理 日志获取 测试报告生成 数据驱动 数据配置 2. ...