一、写在前面
MyBatis基于接口形式的编程主要步骤:
1.创建SqlSessionFactory
对象。
2.根据SqlSessionFactory
对象获取SqlSession
对象。
3.为mapper 接口创建代理对象。
4.使用mapper 接口代理对象执行对应的增删改查操作。
下面就通过分析源码来探索在创建SqlSessionFactory
对象的过程中都发生了什么。
二、SqlSessionFactory
对象创建过程分析
入口程序:
private SqlSessionFactory getSqlSessionFactory() throws IOException {String resource = "mybatis-config.xml";InputStream is = Resources.getResourceAsStream(resource);// 将断点打在下面的代码前return new SqlSessionFactoryBuilder().build(is);}
1.首先会跳到SqlSessionFactoryBuilder
类中的build(InputStream inputStream)
方法。
// ======= SqlSessionFactoryBuilder 类中的方法 =======public SqlSessionFactory build(InputStream inputStream) {return build(inputStream, null, null);}
在该方法中调用了另一个build(InputStream inputStream, String environment, Properties properties)
方法,定义了一个XMLConfigBuilder
对象,通过这个对象调用自身的parse()
方法对配置文件进行解析。
// ======= SqlSessionFactoryBuilder 类中的方法 =======public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {// 创建一个XMLConfigBuilder 解析器XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);// 调用parser 解析器中的parse()方法return build(parser.parse());} catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {inputStream.close();} catch (IOException e) {}}}
2.下面来看看是如何进行文件解析的,跳到XMLConfigBuilder
类中的parse()
方法,在parse()
方法中调用了parseConfiguration(XNode root)
方法,这个方法用于解析配置文件。
// ======= XMLConfigBuilder类中的方法 =======public Configuration parse() {if (parsed) {throw new BuilderException("Each XMLConfigBuilder can only be used once.");}parsed = true;/** * parseConfiguration() 方法用于解析MyBatis 全局配置文件与SQL 映射文件中的相关配置* "/configuration" 就是对应全局配置文件中的<configuration> 标签* parser 是XPathParser 类的实例,通过该对象解析XML 配置文件*/parseConfiguration(parser.evalNode("/configuration"));return configuration;}
下面是parseConfiguration(XNode root)
中的具体源码,在这个方法中会对MyBatis 全局配置文件中的信息与SQL 映射文件中的信息进行解析,并把对应的信息保存在Configuration
对象中。建议具体了解一下其中的settingsElement(settings);
方法与mapperElement(root.evalNode("mappers"));
方法。
// ======= XMLConfigBuilder类中的方法 =======private void parseConfiguration(XNode root) {try {/** * settings、typeAliases、plugins 等用于对应MyBatis 全局配置文件中的标签* 将MyBatis 全局配置文件的标签信息保存在Configuration 对象中*/propertiesElement(root.evalNode("properties"));Properties settings = settingsAsProperties(root.evalNode("settings"));loadCustomVfs(settings);typeAliasesElement(root.evalNode("typeAliases"));pluginElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));reflectorFactoryElement(root.evalNode("reflectorFactory"));// 将<settings> 标签中的设置也保存在Configuration 中settingsElement(settings);// 设置事务的相关配置与数据源environmentsElement(root.evalNode("environments"));databaseIdProviderElement(root.evalNode("databaseIdProvider"));typeHandlerElement(root.evalNode("typeHandlers"));/*** 接着开始解析<mappers>标签中的信息* 在mapperElement() 方法中会对<mappers> 标签下的子标签<mapper> 进行解析,* 解析完<mapper> 标签后,接着调用XMLMapperBuilder 中的方法对SQL 映射文件进行解析,* 并把相应的信息也保存在Configuration 对象中*/mapperElement(root.evalNode("mappers"));} catch (Exception e) {throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);}}
通过上面对parseConfiguration(XNode root)
方法的分析,我们知道MyBatis 全局配置文件与SQL 映射文件中的信息都会保存在Configuration
对象中。这其中还涉及到了很多的方法,在这里就不一一讲述了,大家可以自己进行查看。
3.将信息保存在Configuration
对象中后通过XMLConfigBuilder
类中的parse()
方法返回,作为参数传递到SqlSessionFactory
类中的build(Configuration config)
方法。
最后接着返回一个DefaultSqlSessionFactory
对象。到这里SqlSessionFactory
对象就完成了创建的全部过程。
// ======= SqlSessionFactoryBuilder 类中的方法 =======public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}
调用过程时序图:
三、总结
在SqlSessionFactory
对象创建的过程中,对MyBatis 全局配置文件与SQL 映射文件中的信息进行了解析与保存,为后续创建会话(SqlSession
)提供了基础。这篇博文只是把创建过程进行了分析,略过了其中的一些细节,如果大家感兴趣可以自己参考源码。