1、构建session工厂
// 1、创建一个SqlSessionFactory的 建造者 ,用于创建SqlSessionFactory
// SqlSessionFactoryBuilder中有大量的重载的build方法,可以根据不同的入参,进行构建
// 极大的提高了灵活性,此处使用【创建者设计模式】
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
这是一个创建者设计模式的经典应用:
// 使用builder构建一个sqlSessionFactory,此处我们基于一个xml配置文件
// 此过程会进行xml文件的解析,过程相对比较复杂
SqlSessionFactory sqlSessionFactory = builder.build(Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml"));
源码部分:这里有众多的重载build方法,我们调用的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) {
....
}
从上边的return看,其实核心的代码又回归到了build(parser.parse())
这个构造器。
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
其实,本质上,无论你做了多少工作,你使用xml也好,不使用xml也好,最终都是需要一个Configuration实例,这里保存了所有的配置项。
当然我们可以独立去使用Configuration类构造实例,不使用xml。
例如:
Configuration configuration = new Configuration();
// 创建一个数据源
PooledDataSource pooledDataSource = new PooledDataSource();
pooledDataSource.setDriver("com.mysql.cj.jdbc.Driver");
pooledDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/ydlclass?characterEncoding=utf8&serverTimezone=Asia/Shanghai");
pooledDataSource.setUsername("root");
pooledDataSource.setPassword("root");
Environment environment = new Environment("env",new JdbcTransactionFactory(),new PooledDataSource());
configuration.setEnvironment(environment);
等同于:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/ydlclass?characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
xml的解析过程就是将xml文件转化为Configuration对象,他在启动的时候执行,也就意味着修改配置文件就要重启。所以本环节的重点就到了。
2、配置文件的解析
parser.parse()
这个方法了,这就是在解析xml配置文件。
在build方法中我们看到了如下代码:
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
这一步就是构造一个解析器,根据我们的入参构建一个文档解析器。使用了sax进行xml的解析,我们在讲javaee的时候讲过。
当然,我们要把重点放在parse()方法上:
public Configuration parse() {
...省略不重要的代码
//此处就是解析的核心代码
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
咱们进入这个方法,慢慢分析,其中的内容很多,很明显看到这个方法就是在解析每一个标签。
private void parseConfiguration(XNode root) {
try {
// 处理properties标签
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
// 处理environments标签
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
// 处理mappers标签
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
其实我们看到这里就大致明白了mybaits解析xml的时机和方法了。从这里我们也能基本看出来一个配置文件内能使用的标签,以及书写标签的顺序,因为这个解析过程也是有顺序的,我们随便列出几个标签看看配置文件张什么样子。
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties>
<property name="username" value="root"/>
</properties>
<settings>
<setting name="" value=""/>
</settings>
<typeAliases>
<typeAlias type="com.ydlclass.User" alias="user"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/ydlclass?characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="userMapper.xml"/>
</mappers>
</configuration>
3、mapper文件的解析过程
我们暂且忽略掉其他标签的处理,以mappers
标签为例继续深