前言
在GitHub Fork一份MyBatis源码后,我们在IDE中打开,运行测试用例AutoConstructorTest类中的fullyPopulatedSubject()方法,为了找到熟悉的感觉,我在同级目录的AutoConstructorMapper类和AutoConstructorMapper.xml文件对应添加了一个findById的查询。
加载全局配置文件流程
Tips:可以用Debug的模式来运行来打断点,看看Configuration中的值
1.加载全局配置文件mybatis-config.xml
try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/autoconstructor/mybatis-config.xml")) {// 调用 #1SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);}
2.SqlSessionFactoryBuilder类中生成SqlSessionFactory
// #1public SqlSessionFactory build(Reader reader) {// 调用#2return build(reader, null, null);}// #2public SqlSessionFactory build(Reader reader, String environment, Properties properties) {try {XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);// 调用#3 parser.parse()// 调用#4return 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.}}}
3.XMLConfigBuilder类中解析Configuration
// #3public Configuration parse() {if (parsed) {throw new BuilderException("Each MyXMLConfigBuilder can only be used once.");}parsed = true;// 调用#5parseConfiguration(parser.evalNode("/configuration"));return configuration;}// #5 XPathParser解析器会解析各种标签private void parseConfiguration(XNode root) {try {//issue #117 read properties firstpropertiesElement(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 #631environmentsElement(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);}}
4.获取Configuration对象


经过以上几个步骤就会得到Configuration这个超级复杂的核心对象。
如图所示,拿其中mappedStatements来说,是个Map结构,它里面的key存储的就是*Mapper.xml中select/insert/update/delete标签中的id值,这里我们看findById,里面的mappedStatement存储这个关于这个statement的各种信息,statement的id由namespace+标签中的id来保证唯一性,具体细节可以打个断点查看下。
dataSource也正是我们从mybatis-config.xml文件中加载到的数据源配置项。
5.通过Configuration获取到SqlSessionFactory
// #4public SqlSessionFactory build(Configuration config) {// 使用DefaultSqlSessionFactory创建return new DefaultSqlSessionFactory(config);}
小结
本篇通过MyBatis提供的AutoConstructorTest测试类,我们跟踪了下全局配置文件的加载流程,xml中配置的一个
本篇只是粗略的探讨了几个主要的类:
- SqlSessionFactoryBuilder
- XMLConfigBuilder
- Configuration
- XPathParser
- SqlSessionFactory
但其实在XMLConfigBuilder中解析各个标签用到的XNode和其他一些类就没有去关心了或者说不是本篇的重点,正如第一篇讲到,把控好主线才不容易走丢。
请你相信我所说的都是错的
