Mybatis执行流程分析
mybatis全局配置文件
mybatis全局配置文件中涉及的标签如下图所示
配置文件解析
public static void main(String[] args) throws IOException {
// 读取配置文件
InputStream is = Resources.getResourceAsStream("org/apache/ibatis/builder/MapperConfig1.xml");
// 创建SqlSessionFactory工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(is);
// 使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//使用SqlSession创建Dao接口的代理对象
AuthorMapper authorMapper = session.getMapper(AuthorMapper.class);
List<Author> authors = authorMapper.selectAllAuthors();
//释放资源
session.close();
is.close();
}
下面我们来进行源码分析。
配置文件的解析&创建SqlSessionFactory
配置文件的解析主要涉及到的类如下:XMLConfigBuilder、XPathParser、XPath、XNode,其中XPath、XNode是对
1、build方法内部首先会根据输入流等信息创建XMLConfigBuilder类的实例对象,然后调用XMLConfigBuilder实例的parse方法对配置文件进行解析;这里需要注意的是parse方法最后返回的是一个Configuration对象
2、parse方法则是调用了XPath对象的evalNode方法对配置文件中的configuration节点进行解析,会把节点内容放在XNode对象中然后返回;
3、parseConfiguration方法会对configuration节点解析出来的内容再进行解析,会把解析出来的内容放在configuration对象中;实际上配置文件中的内容解析出来后都会存到Configuration中。
4、parseConfiguration方法中主要做的事如下:
- 解析 properties节点
/**
* 解析 properties节点
* <properties resource="mybatis/db.properties" />
* 解析到org.apache.ibatis.parsing.XPathParser#variables
* org.apache.ibatis.session.Configuration#variables
*/
// issue #117 read properties first
propertiesElement(root.evalNode("properties"));
- 解析settings节点
/**
* 解析我们的mybatis-config.xml中的settings节点
* 具体可以配置哪些属性:http://www.mybatis.org/mybatis-3/zh/configuration.html#settings
* <settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
..............
</settings>
*
*/
Properties settings = settingsAsProperties(root.evalNode("settings"));
- 解析
/**
* 基本没有用过该属性
* VFS含义是虚拟文件系统;主要是通过程序能够方便读取本地文件系统、FTP文件系统等系统中的文件资源。
Mybatis中提供了VFS这个配置,主要是通过该配置可以加载自定义的虚拟文件系统应用程序
解析到:org.apache.ibatis.session.Configuration#vfsImpl
*/
loadCustomVfs(settings);
- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
/**
* 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
* SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
* 解析到org.apache.ibatis.session.Configuration#logImpl
*/
loadCustomLogImpl(settings);
- 解析别名
/**
* 解析别名
* <typeAliases>
<typeAlias alias="Author" type="cn.tulingxueyuan.pojo.Author"/>
</typeAliases>
<typeAliases>
<package name="cn.tulingxueyuan.pojo"/>
</typeAliases>
解析到oorg.apache.ibatis.session.Configuration#typeAliasRegistry.typeAliases
*/
typeAliasesElement(root.evalNode("typeAliases"));
- 解析插件
/**
* 解析我们的插件(比如分页插件)
* mybatis自带的
* Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
解析到:org.apache.ibatis.session.Configuration#interceptorChain.interceptors
*/
pluginElement(root.evalNode("plugins"));
- 设置settings
// 设置settings 和默认值
settingsElement(settings);
- 解析mybatis环境
/**
* 解析mybatis环境
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="root"/>
<property name="password" value="Zw726515"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
* 解析到:org.apache.ibatis.session.Configuration#environment
* 在集成spring情况下由 spring-mybatis提供数据源 和事务工厂
*/
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
- 解析数据库厂商
/**
* 解析数据库厂商
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
<property name="MySql" value="mysql" />
</databaseIdProvider>
* 解析到:org.apache.ibatis.session.Configuration#databaseId
*/
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
- 解析类型处理器
/**
* 解析我们的类型处理器节点
* <typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
解析到:org.apache.ibatis.session.Configuration#typeHandlerRegistry.typeHandlerMap
*/
typeHandlerElement(root.evalNode("typeHandlers"));
- 解析mapper文件
/**
* 解析mapper文件(SQL映射文件)
*
resource:来注册我们的class类路径下的
url:来指定我们磁盘下的或者网络资源的
class:
若注册Mapper不带xml文件的,这里可以直接注册
若注册的Mapper带xml文件的,需要把xml文件和mapper文件同名 同路径
-->
<mappers>
<mapper resource="mybatis/mapper/EmployeeMapper.xml"/>
<mapper class="com.tuling.mapper.DeptMapper"></mapper>
<package name="com.tuling.mapper"></package>
-->
</mappers>
* package 1.解析mapper接口 解析到:org.apache.ibatis.session.Configuration#mapperRegistry.knownMappers
2.
*/
mapperElement(root.evalNode("mappers"));
到这里配置文件就解析完了,mybatis会根据configuration对象创建SqlSessionFactory类的对象。
获取SqlSession
调用openSession()方法获取SqlSession
创建Executor的对象,这里会根据类型去创建对应的Executor
最后一行的代码:interceptorChain.pluginAll(executor)的作用是会调用所有拦截器对象的plugin方法
最后执行到Plugin类的wrap方法对executor进行包装
执行getMapper方法
实际上调用的是configuration对象的getMapper方法
而configuration对象则是调用了mapperRegistry对象的getMapper方法;
MapperRegistry简介
- MapperRegistry实质上是一个Map,里面注册了启动过程中解析的各种mapper.xml;
- MapperRegistry的key是接口的Class类型,MapperRegistry的value是MapperProxyFactory,用于生成对应的MapperProxy(动态代理类);
- 由于Mybatis中的Mapper接口没有实现类,所以MapperProxy这个代理对
象中没有委托类,也就是说MapperProxy干了代理类和委托类的事情
接着往下看;mapperRegistry的getMapper方法则是调用了mapperProxyFactory的newInstance方法
MapperProxyFactory介绍
- 在通过sqlSession获取Mapper时,其实先获取到的是这个工厂,然后通过这个工厂创建Mapper的动态代理类
MapperProxyFactory中的newInstance方法如下:
这里用到了动态代理,最后会调用MapperProxy中重写的的invoke方法
execute方法如下:
接着会调用executeForManay方法
selectList方法如下:
接着会执行exector中的query方法
可以看到最后使用的还是JDBC中的Statement,最后把查询到的结果返回查询流程就结束了。
下面mybatis总的一个处理流程:
mybatis一个大致的执行流程分析就到这里结束了,后面会继续详细讲解执行流程中涉及到的相关内容。
参考
- Mybatis文档
- mybatis学习视频