本篇开始分析关于MyBatis的使用和源码分析
1.MyBatis是如何运行的
这里我推荐直接进入官网上看Demo 官网入门Demo,为什么?
之前个人也没有习惯看官网,都是习惯直接百度谷歌搜索别人写的教程,这有什么缺点呢?
- 内容质量参差不齐,无法有效筛选,浪费时间
- 每篇内容重复程度高,且大多可能都是官网拷贝
- 没有看官网来的全面
当然如果官网的文档提供不足,那么可以另寻他路。
OK,言归正传,我们进入正题:
首先在pom文件中添加
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
然后通过加载XML文件资源:
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
这里我们先不需要在乎有没有这样一个资源文件,我们先抓住MyBatis是如何来进行解析资源的,也就是SqlSessionFactoryBuilder类。
2. SqlSessionFactoryBuilder源码分析
这个类就一个方法名,我们简单看下:
SqlSessionFactoryBuilder方法
可以看到目的就是为了构建出SqlSessionFactory,我们找一个通用的方法进行分析
2.1 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.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
我们看到这里又出现了一个XMLConfigBuilder,见名知意,猜想这个类就是解析XML资源文件的。
3.XMLConfigBuilder源码分析
我们在分析源码的时候,先看属性和构造方法,再来看相应的方法,那么这个类的属性和构造方法是:
public class XMLConfigBuilder extends BaseBuilder {
private boolean parsed;
private final XPathParser parser;
private String environment;
private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
//日志输出相关
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
我们了解下它的组成结构,这里我们看到他继承了BaseBuilder,并且内部属性有两个我们是不太熟悉的类:
1.XPathParser
2.ReflectorFactory
那么在我们的技术债上加上
技术债
- XPathParser
- ReflectorFactory
再来看继承类BaseBuilder的代码。
3.1 BaseBuilder源码分析
public abstract class BaseBuilder {
/**
* 全局资源配置
*/
protected final Configuration configuration;
/**
* 类型别名注册器
*/
protected final TypeAliasRegistry typeAliasRegistry;
/**
* 类型处理注册器
*/
protected final TypeHandlerRegistry typeHandlerRegistry;
public BaseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
}
重点:每个继承BaseBuilder类的方法都可以获取到Configuration、TypeAliasRegistry、TypeHandlerRegistry三个类
这里又欠下了3个类的技术债,我们补充上:
技术债
- XPathParser
- ReflectorFactory
- Configuration
- TypeAliasRegistry
- TypeHandlerRegistry
这个类都是辅助方法,没有什么主逻辑方法,所以我们继续回到他的继承类XMLConfigBuilder,大家是否还记的在<2.1>中我们使用了XMLConfigBuilder的parse()方法
3.2 XMLConfigBuilder#parse源码解析
//XMLConfigBuilder
private boolean parsed;
private final XPathParser parser;
private String environment;
private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
public Configuration parse() {
//初始化默认为false,代表是否解析过
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
这里涉及到了使用XPathParser解析资源文件下的某个标签,然后使用parseConfiguration方法解析
3.2.1 XMLConfigBuilder#parseConfiguration
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
loadCustomLogImpl(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);
}
}
这里我们使用过MyBatis配置文件的就会有点熟悉了,这里的每个方法都是解析资源文件中的一个标签,这里避免大家有些遗漏,我在官网中MyBatis官网XML配置
这块逻辑大家应该不难理解,就是根据XML标签去取资源文件配置内容。
4.今日总结
今天我们查看了官网使用MyBatis使用流程,并且对于解析XML文件的流程进行了一定的梳理。
进而输出:
技术债
- XPathParser
- ReflectorFactory
- Configuration
- TypeAliasRegistry
- TypeHandlerRegistry
之后便是分析到XMLConfigBuilder根据标签进行分析这步。
网友评论