Mybatis源码解析2:全局配置
- 1.项目结构
- 2. 源码分析
- 2.1.SqlSessionFactoryBuilder#build(java.io.InputStream)
- 2.2 XMLConfigBuilder构造器
- 2.3 解析XMLConfigBuilder#parse
- 2.4 解析配置 XMLConfigBuilder#parseConfiguration
1.项目结构
源码地址:
项目结构:
2. 源码分析
2.1.SqlSessionFactoryBuilder#build(java.io.InputStream)
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
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.
}
}
}
- 创建XMLConfigBuilder对象。Mybatis的xml分为两种,一种是配置文件xml,主要是用来全局配置,比如拦截器、别名、还有mapper文件路径或包名路径等(官网列出了所有的配置属性)。还有一种是Mapper.xml,也是用来声明要执行的Sql,一般会与Mapper接口进行绑定。从名字上来看,XMLConfigBuilder显然就是用来解析第一种xml的对象。
- XMLConfigBuilder#parse对配置文件进行解析,将解析的数据封装到Configuration对象里面。最终将全局配置Configuration封装DefaultSqlSessionFactory对象里面返回。
2.2 XMLConfigBuilder构造器
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
commonConstructor(validation, variables, entityResolver);
this.document = createDocument(new InputSource(inputStream));
}
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;
}
- XMLConfigBuilder构造器创建了XPathParser。而XPathParser里面的xpath是通过jdk里面rt.jar实现的,xpath主要是对xml文档进行解析(可以理解为从Document对象中获信息,比如子节点、当前节点的属性等)。在XPathParser对象创建的过程中也调用了XPathParser#createDocument方法,将配置文件流解析成了Document对象。
- XMLConfigBuilder里面创建了全局的Configuration对象,这个对象在Mybatis整个流程中都被使用
2.3 解析XMLConfigBuilder#parse
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
- XPathParser#evalNode(java.lang.String) 方法通过xpath解析configuration根节点,将解析出的节点信息封装成mybatis的XNode对象,方便后续获取当前节点的属性和子节点的信息。
- 对文档的节点信息进行解析,封装在全局配置Configuration里面
2.4 解析配置 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);
}
}
- 该方法主要是从XNode中读取config.xml配置,并且将配置封装到全局变量Configuration里面,包含了别名、拦截器、反射工厂、数据源、类型转换器、mapper的资源信息等,这里就不一一说明了。这些配置为后面Sql的执行奠定了基础。
- 后面会对mapperElement(root.evalNode(“mappers”))方法解析