Mybatis官方文档:https://mybatis.org/mybatis-3/zh/index.html
Mybatis源码(3.5.8-SNAPSHOT版本)下载:https://github.com/mybatis/mybatis-3
从官网Demo代码来入手:https://mybatis.org/mybatis-3/zh/getting-started.html
1、mybatis-config.xml配置文件解析 ,得到输入流;
底层使用java.io下的InputStream和Reader两个抽象类,通过Mybatis的Resources获取两种流的方法:
- 字节输入流:Reader reader = Resources.getResourceAsReader(resource);
- 字符流:InputStream inputStream = Resources.getResourceAsStream(resource);
// 官网Demo代码
// 配置文件路径
String resource = "org/mybatis/example/mybatis-config.xml";
// 读取mybatis-config.xml,通过Resources获取文件输入流
// 详情见Resources和ClassLoaderWrapper源码分析
InputStream inputStream = Resources.getResourceAsStream(resource);
// 解析xml配置文件,得到SqlSessionFactory,具体解析流程如下
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2、构建SqlSessionFactory对象
SqlSessionFactory为工厂类,单例模式,仅仅存储了Mybatis配置对象Configuration信息;就像名称一样,专门用来生产SqlSession对象,即会话;
SqlSessionFactoryBuilder:
- SqlSessionFactoryBuilder类:SqlSessionFactoryBuilder没有构造方法,所有方法都是build()方法;
- build方法都是返回SqlSessionFactory对象,所以可以知道构建SqlSessionFactory对象的方法为new SqlSessionFactoryBuilder().build();
- build方法入参可知得到SqlSessionFactory对象只有三种方式:InputStream(字节流)、Reader(字符流)、Configuration(配置类)。
- 无论InputStream还是Reader都是对mybatis-config.xml配置文件的解析,从最终生成SqlSessionFactory对象的build来看SqlSessionFactory必要信息是Configuration(配置类)!;所以InputStream和Reader入参的build中包含了XMLConfigBuilder对象来解析XML文件配置到Configuration配置类,后面介绍XMLConfigBuilder对象的具体源码。
- 而最终生成的SqlSessionFactory对象是通过new DefaultSqlSessionFactory(config);
// SqlSessionFactoryBuilder源码
package org.apache.ibatis.session;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
public class SqlSessionFactoryBuilder {
// SqlSessionFactoryBuilder来读取InputStream字节流的配置信息
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// 创建XMLConfigBuilder对象
// 对应下面源码分析3、SqlSessionFactoryBuilder().build()中构建XMLConfigBuilder对象
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// parser.parse()来生成Configuration配置对象,传给最终的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.
}
}
}
// SqlSessionFactoryBuilder来读取Reader字符流的配置信息
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.
}
}
}
// SqlSessionFactory对象生成的必要方法,必要参数为Configuration配置对象
public SqlSessionFactory build(Configuration config) {
// DefaultSqlSessionFactory为实现SqlSessionFactory接口的默认类
return new DefaultSqlSessionFactory(config);
}
}
DefaultSqlSessionFactory:
- DefaultSqlSessionFactory类实现了SqlSessionFactory接口;
- 唯一的成员变量configuration来管理Configuration配置对象;
- 唯一的构造方法在对象实例化时来给configuration赋值;
- 实现了SqlSessionFactory接口的各种openSession方法和getConfiguration方法;
- openSession创建SqlSession对象的各种方法,在"源码分析构建SqlSeesion对象"中具体分析。
// DefaultSqlSessionFactory源码
package org.apache.ibatis.session.defaults;
// DefaultSqlSessionFactory类实现了SqlSessionFactory接口
public class DefaultSqlSessionFactory implements SqlSessionFactory {
// 唯一的成员变量configuration来管理Configuration配置对象
private final Configuration configuration;
// 唯一的构造方法在对象实例化时来给configuration赋值
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
return openSessionFromDat