摘要
主要讲解SqlSessionFactory对象创建过程和源码分析.在SqlSessionFactory
对象创建的过程中,对MyBatis 全局配置文件与SQL 映射文件中的信息进行了解析与保存,为后续创建会话(SqlSession
)提供了基础
- 1.创建
SqlSessionFactory
对象。 - 2.根据
SqlSessionFactory
对象获取SqlSession
对象。 - 3.为mapper 接口创建代理对象。
- 4.使用mapper 接口代理对象执行对应的增删改查操作
SqlSessionFactory源码分析
读取核心配置文件并返回InputStream流对象。==>根据InputStream流对象解析出Configuration对象,然后创建SqlSessionFactory工厂对象==> 根据一系列属性从SqlSessionFactory工厂中创建SqlSession==> 从SqlSession中调用Executor执行数据库操作&&生成具体SQL指令==>对执行结果进行二次封装==> 提交与事务
private SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
// 将断点打在下面的代码前
return new SqlSessionFactoryBuilder().build(is);
}
1、首先会跳到SqlSessionFactoryBuilder类中的build(InputStream inputStream)方法。
// ======= SqlSessionFactoryBuilder 类中的方法 =======
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
在该方法中调用了另一个build(InputStream inputStream, String environment, Properties properties)方法,定义了一个XMLConfigBuilder对象,通过这个对象调用自身的parse()方法对配置文件进行解析。
// ======= SqlSessionFactoryBuilder 类中的方法 =======
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// 创建一个XMLConfigBuilder 解析器
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// 调用parser 解析器中的parse()方法
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
}
}
}
2.跳到XMLConfigBuilder类中的parse()方法,在parse()方法中调用了parseConfiguration(XNode root)方法,这个方法用于解析配置文件。
// ======= XMLConfigBuilder类中的方法 =======
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
/**
* parseConfiguration() 方法用于解析MyBatis 全局配置文件与SQL映射文件中的相关配置
* "/configuration" 就是对应全局配置文件中的 标签
* parser 是XPathParser 类的实例,通过该对象解析XML 配置文件
*/
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
下面是parseConfiguration(XNode root)中的具体源码,在这个方法中会对MyBatis 全局配置文件中的信息与SQL 映射文件中的信息进行解析,并把对应的信息保存在Configuration对象中。建议具体了解一下其中的settingsElement(settings);方法与mapperElement(root.evalNode("mappers"));方法。
// ======= XMLConfigBuilder类中的方法 =======
private void parseConfiguration(XNode root) {
try {
/**
* settings、typeAliases、plugins 等用于对应MyBatis 全局配置文件中的标签
* 将MyBatis 全局配置文件的标签信息保存在Configuration 对象中
*/
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"));
// 将 标签中的设置也保存在Configuration 中
settingsElement(settings);
// 设置事务的相关配置与数据源
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
/**
* 接着开始解析标签中的信息
* 在mapperElement() 方法中会对 标签下的子标签 进行解析,
* 解析完 标签后,接着调用XMLMapperBuilder 中的方法对SQL 映射文件进行解析,
* 并把相应的信息也保存在Configuration 对象中
*/
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
通过上面对parseConfiguration(XNode root)方法的分析,我们知道MyBatis 全局配置文件与SQL 映射文件中的信息都会保存在Configuration 对象中。
3.将信息保存在Configuration对象中后通过XMLConfigBuilder类中的parse()方法返回,作为参数传递到SqlSessionFactory类中的build(Configuration config)方法。
最后接着返回一个DefaultSqlSessionFactory对象。到这里SqlSessionFactory对象就完成了创建的全部过程。
// ======= SqlSessionFactoryBuilder 类中的方法 =======
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}