MyBatis框架的启动前期需要加载相关的XML配置信息。从官网上我们可以了解到他具有十几个节点。其中笔者认为比较重要的节点是settings节点、properties节点、environments节点、 transactionManager节点。至于相关的作用到官网看过一篇都会明白。

MyBatis框架的XML配置到底有几个节点,这个必须去查看一下相关的DTD文件才行。DTA文件就在包名为org.apache.ibatis.builder.xml的下面。由于显示的问题笔者只复制出部分来。

<?xml version="1.0" encoding="UTF-8" ?>

<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>

<!ELEMENT databaseIdProvider (property*)>
<!ATTLIST databaseIdProvider
type CDATA #REQUIRED
>

从上面我们就可以看到根节点就是configuration。同时我们也能找到上面笔者提到的比较重要的几个节点。

1.properties 节点:可以把它理解为变量吧。事实上他可以是一个properties文件。
2.settings 节点:MyBatis框架有一些内部需要设置的配置信息。请查看官网对于settings的介绍。
3.typeAliases 节点:设置相应的别名。这样子可以简少重复的编写。
4.typeHandlers 节点:官网叫为类型处理器,大部用于结果集应射到对象的时候需要。
5.environments 节点:这个节点按道理来讲是大家最清楚的。因为设置数据连接的信息就在这里。
6.mappers 节点:对象模型与数据表映射的信息。
注意:笔者这里只是写出可能常用的。

知道了上面的信息之后,在去看对应的源码你就会发现很简单——大部分都是一一对应的。 来,让我们从上一章中讲到的切入口类(SqlSessionFactoryBuilder)的build方法查看进去。SqlSessionFactoryBuilder类里面重载了很多build的方法。但是所有的方法最后都会流入下面的方法中去。

 public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}

从上面的代码中我们可以看到这个方法有三个参数:

1.Reader reader:XML配置所在的文件流。

2.String environment:指定要执行的环境ID。

3.Properties properties:加载的变理信息。

XMLConfigBuilder类的作用就是用于加载XML配置文件,也可以理解为读取。他的parse方法充分的体现出他的作用来。

  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 {
Properties settings = settingsAsPropertiess(root.evalNode("settings"));
//issue #117 read properties first
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"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}

从要上面的俩个方法中我们可以看到很眼熟的代码字眼。相信不难看出就是加载各个节点上的信息。事实上如果我们查看一下parse方法的返回类型我们就可以知道这个步骤最后就是为了生成相应的Configuration类实例。可以这样子讲有关配置信息加载最后一定都在Configuration类实例里面。所以查看Configuration类就变得很有意义。源码笔者就不贴出来占地方。

XMLConfigBuilder类源码里面有俩个地方是笔者比较喜欢的。一个是简单封装了读取XML的操作类——XPathParser类。可能对于JAVA来讲这不算什么。笔者从事过C#开发,所以感觉比较深吧。他只是做了一个简单的封装。可是笔者看起来在读取XML便得更加载顺心了——可读性更强了。

 public String evalString(Object root, String expression) {
String result = (String) evaluate(expression, root, XPathConstants.STRING);
result = PropertyParser.parse(result, variables);
return result;
} public Boolean evalBoolean(String expression) {
return evalBoolean(document, expression);
} public Boolean evalBoolean(Object root, String expression) {
return (Boolean) evaluate(expression, root, XPathConstants.BOOLEAN);
} public Short evalShort(String expression) {
return evalShort(document, expression);
}

上面是XPathParser类读取XML文件值各自需要调用的方法。我们可以清楚的可以知道返回类型和调用的节点。笔者认为简单一小步,可是明理一大步。XMLConfigBuilder类源码里面还有一个笔者认为需要去注意学习的地方——MetaClass类。他的功能跟反射有关系,同时用到ReflectorFactory类和Reflector类。他这样子封装之后用到反射功能便得更加的容易理解和可观。过多的介绍还不如自己亲自去看一下体验一下。

好了,现在让我们回过头在来看看build方法最后返回什么才是最重要的。从源码中我们知道他返回的是一个DefaultSqlSessionFactory类型。

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

本章的重点类出来了。当程序执行到上面的方法的时候,说明加载配置信息的工作已经结束了。一个新的工作又要开始了。让我们在看一下笔者的例子代码吧。

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
IProductMapper dao = session.getMapper(IProductMapper.class);

笔者调用的没有参数的openSession方法。从这个方法里我们可以看到他又去调用了一个叫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);
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();
}
}

上面的方法中有几个比较重要的类:Executor类、DefaultSqlSession类。其中特别是Executor类。本章就不明讲。后面会讲到。我们可以看到最后返回类是DefaultSqlSession类。对于数据库的增删改查就依赖这个类。

显然文章到了这里就已经把接下来要去了解工作做了一个明确的方法——了解Executor类的功能。这样子我们就可以进一步的了解框架了。

MyBatis 源码分析——配置信息的更多相关文章

  1. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  2. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  3. MyBatis源码分析(5)——内置DataSource实现

    @(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...

  4. MyBatis源码分析(2)—— Plugin原理

    @(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...

  5. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  6. MyBatis源码分析之环境准备篇

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

  7. Mybatis源码分析-StatementHandler

    承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...

  8. mybatis源码分析(一)

    mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...

  9. 【MyBatis源码分析】环境准备

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

随机推荐

  1. Django Rest Framework源码剖析(五)-----解析器

    一.简介 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数据格式,比如xml,所以需要解析这类数 ...

  2. 类加载, 静态变量初始化, String不可变, 泛型使用, 内部类

    1.java变量类型 java变量类型分:基本数据类型变量和Object数据类型变量,变量也是占用者内存的 例如: int i = 3; i这个变量保存的就是整形3, 占32位 Object a = ...

  3. GAN初步——本质上就是在做优化,对于生成器传给辨别器的生成图片,生成器希望辨别器打上标签 1,体现在loss上!

    from:https://www.sohu.com/a/159976204_717210 GAN 从 2014 年诞生以来发展的是相当火热,比较著名的 GAN 的应用有 Pix2Pix.CycleGA ...

  4. [Luogu5048] [Ynoi2019模拟赛]Yuno loves sqrt technology III[分块]

    题意 长为 \(n\) 的序列,询问区间众数,强制在线. \(n\leq 5\times 10^5\). 分析 考虑分块,暴力统计出整块到整块之间的众数次数. 然后答案还可能出现在两边的两个独立的块中 ...

  5. Flutter - 创建底部导航栏

    之前写过的一篇文章介绍了 Flutter - 创建横跨所有页面的侧滑菜单, 这次就一起来学习一下底部导航栏. 底部导航栏在ios平台上非常常见,app store就是这样的风格.还有就是大家最常用的微 ...

  6. vs2013 std::sort 分析

    由于之前在debug模式下发现stl的sort简直慢到不能忍,所以自己写了一个sgi的sort,后来发现在release模式下,vs自带的sort快的不行,就研究了下. 这里有些和sgi-stl相通的 ...

  7. 【DDD】领域驱动设计实践 —— 业务建模战术

    本文结合团队在COMMUNITY(社区服务系统)业务建模过程中的实践经验,总结得到一些DDD业务建模的小招数,不一定是完美的,但是对我们团队来说很有效用,希望能帮到其他人.后面会陆续将项目中业务建模的 ...

  8. java后台面试知识点总结

    本文主要记录在准备面试过程中遇到的一些基本知识点(持续更新) 一.Java基础知识 1.抽象类和接口的区别 接口和抽象类中都可以定义变量,但是接口中定义的必须是公共的.静态的.Final的,抽象类中的 ...

  9. 173. Insertion Sort List【LintCode by java】

    Description Sort a linked list using insertion sort. Example Given 1->3->2->0->null, ret ...

  10. spring boot 2.0 源码分析(二)

    在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数. 先把这段run函数的代码贴出来: /** * Run the ...