最近阅读了《Java Persistence with MyBatis 3》一书,对Mybatis的各类配置及使用有了更深入的的了解。 进而产生了对Mybatis源码进行阅读解析的想法,就从这篇文章开始吧。先对Mybatis框架的初始化进行解析

Mybatis 初始化做了什么

  框架的初始化及加载运行时所需的配置信息,而Mybatis的配置则在mybatis-config.xml文件中。查看dtd文件即可知其主要标签结构如下:

  • configuration 配置
  • properties 属性
  • settings 设置
  • typeAliases 对象别名命名
  • typeHandlers 类型处理器
  • objectFactory 对象工厂
  • plugins 插件
  • environments 环境
    • environment 环境变量
      • transactionManager 事务管理器
      • dataSource 数据源
  • mappers

   众所周知,要使上述Mybatis配置加载入Mybatis内部首先要创建SqlSession对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MySqlSessionFactory {

private static SqlSessionFactory sqlSessionFactory;

public static SqlSessionFactory getSqlSessionFactory(){
if (sqlSessionFactory == null){
InputStream inputStream;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e){
e.printStackTrace();
throw new RuntimeException();
}
}

return sqlSessionFactory;
}


public static SqlSession openSession() {
return getSqlSessionFactory().openSession();
}

}

由上方代码可见此次Mybatis初始化源码阅读之旅的入口即为:SqlSessionFactoryBuilder().build()方法。进一步阅读,即可发现Mybatis中使用org.apache.ibatis.session.Configuration类作为配置信息对象的存储容器

1
2
3
4
5
6
7
8
9
10
11
public class Configuration {
protected Environment environment;
protected Properties variables = new Properties();
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
protected final InterceptorChain interceptorChain = new InterceptorChain();
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();

...
}

由此可见,Mybatis初始化的过程基本可以看成是Configuration对象创建的过程,接下来就将深入探讨Mybatis是如何通过XML配置的方式构建COnfiguration对象。

MyBatis基于XML配置文件创建Configuration对象的过程

时序图:

image_1ceo09j2j2b7jso1hf5lp1tvf9.png-48.1kB

由上图所示,mybatis初始化要经过简单的以下几步:

  1. 调用SqlSessionFactoryBuilder对象的build(inputStream)方法;
  2. SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;
  3. SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法;
  4. XMLConfigBuilder对象返回Configuration对象;
  5. SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;
  6. SqlSessionFactoryBuilder返回DefaultSessionFactory对象。

创建Configuration对象的过程

XMLConfigBuilder调用parse()方法:会从XPathParser中取出 节点对应的Node对象,然后解析此Node节点的子Node:properties, settings, typeAliases,typeHandlers, objectFactory, objectWrapperFactory, plugins, environments,databaseIdProvider, mappers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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);
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);
}
}

解析environments节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
// 创建sqlSessionFactory时未指定默认环境
if (environment == null) {
// 则将environments节点default属性设置为默认环境
environment = context.getStringAttribute("default");
}

//循环所有设置的环境
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
//只对指定的环境进行加载
if (isSpecifiedEnvironment(id)) {
//1.创建事务工厂 TransactionFactory
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
//2.创建数据源DataSource
DataSource dataSource = dsFactory.getDataSource();
//3. 构造Environment对象
Environment.Builder environmentBuilder = new Environment.Builder(id)
.transactionFactory(txFactory)
.dataSource(dataSource);
//4. 将创建的Envronment对象设置到configuration 对象中
configuration.setEnvironment(environmentBuilder.build());
}
}
}
}