SqlSessionFactory是Mybatis的一个重要的对象,是用来创建SqlSession的。在创建SqlSessionFactory时候,mybatis主要是解析了mybatis-config.xml和我们定义的各种Mapper文件,下面我们看看mybatis创建的SqlSessionFactory的具体过程。(在展示源码时仅仅展示关键的代码,对于剩余部分,感兴趣的小伙伴可以自行查看。)
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(resourceAsStream);
上面简单的三行代码,就是我们创建SqlSessionFactory的代码。下面我们看看Mybatis在创建SqlSessionFactory的具体过程。(SqlSessionFactoryBuilder中build的方法)
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
...
} finally {
...
}
}
在build的时候,mybatis主要创建了一个XMLConfigBuilder(xcb);下面我们看看xcb。(XMLConfigBuilder的构造函数)
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
this.parser = parser;
...
}
在创建xcb的时候有三个重要的对象,XPathParser、Configuration、 XMLMapperEntityResolver
- XPathParser(xpp):用来解析mybatis-config.xml。
- Configuration:很重要,用来存储各种配置,还有我们。
- XMLMapperEntityResolver:用来解析各种mapper的。
下面我们看看 xcb中的parse方法
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
在parse中没做什么操作,接下来我们看看parseConfiguration方法
private void parseConfiguration(XNode root) {
//获取setting标签中所有的name和value 并转成了properties
Properties settings = settingsAsPropertiess(root.evalNode("settings"));
//xxx.properties中配置的k:v 可以作为内部可用变量,然后把这个解析出的可用变量集合赋值一份给 Configuration和XPathParser各一份
//用于替换占位符 等信息,相当于内部的环境变量
propertiesElement(root.evalNode("properties"));
//加载虚拟文件系统,用户获取容器内的资源
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
//设置xml
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
//解析typeHandler
typeHandlerElement(root.evalNode("typeHandlers"));
//解析mapper
mapperElement(root.evalNode("mappers"));
}
propertiesElement 这个方法会把我们配置的.properties文件和property标签中的key value读出来
然后作为mybatis整个运行环境中的环境变量进行使用。例如数据源中的${url}…等信息就是从环境变量中来的。
这里面主要是解析mybatis-config.xml中的各种标签,主要是把mybatis-config.xml我们配置的值读出来,然后存储到Configuration对象中,感兴趣的小伙伴很简单。mapperElement方法很重要下一节我们单独来说。