简介
你了解MyBatis多少?了解SqlSessionFactory构建过程吗?了解XML解析过程吗?了解Mapper代理都干了什么事儿吗?本章以MyBatis 3.5.3带你一起阅读源代码,让你不在局限于会用,而是领会MyBatis的精髓。
通过简单Mybatis工程一步一步深入
Maven依赖包
<
User 实体类
目录:comuserUser.java
@Data
UserMapper 接口
目录:comuserUserMapper.java
public
UserMapper.xml 配置文件
目录resourcesmapperUserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
Mybaits 配置文件
目录:resourcesconfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
JDBC配置文件
目录:resourcesjdbc.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://192.168.1.100:3306/mybaits
username=root
password=root
Log配置文件
目录:resourceslog4j.properties
log4j.rootLogger=DEBUG, stdout
log4j.logger.org.mybatis.example.BlogMapper=TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
数据库
CREATE
测试类Test
public
输出日志
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1579132337.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5e1fa5b1]
DEBUG [main] - ==> Preparing: select user_id, mobile from `user` where user_id = ?
DEBUG [main] - ==> Parameters: 1(Long)
DEBUG [main] - <== Total: 1
User(userId=1, mobile=13100001001)
Disconnected from the target VM, address: '127.0.0.1:52936', transport: 'socket'
简要解析
String
先使用Resources.getResourceAsReader(resource)加载配xml置文件,然后SqlSessionFactoryBuilder的build方法构建SqlSessionFactory,这里主要关注SqlSessionFactory的构建过程。
1、SqlSessionFactoryBuilder委托XMLConfigBuilder
2、XMLConfigBuilder创建 XMLMapperEntityResolver DTD加载器,并委托XPathParser解析器解析mybaits.xml配置文件
3、XPathParser解析器使用XPathFactory加载xml和DocumentBuilderFactory构建Document
4、XMLConfigBuilder使用第三步的结果创建Configuration,并给Configuration赋值,最后完成XMLConfigBuilder的创建
5、SqlSessionFactoryBuilder中调用XMLConfigBuilder的parse()解析方法,解析mybaits.xml中各个节点
6、XMLConfigBuilder解析mappers节点,遍历mapper路径配置列表
7、构建XMLMapperBuilder加载上面得到的mapper配置文件,并调用parse()解析mapper配置文件中各个节点。
8、XMLMapperBuilder中把路径"mapper/UserMapper.xml"、namespace、namespace反射得到的Class等加入Configuration
9、XMLMapperBuilder调用MapperRegistry.addMapper(Class<T> type),构建MapperProxyFactory向Mapper已知管理器中注册
9、SqlSessionFactoryBuilder通过上面创建的Configuration构造DefaultSqlSessionFactory
SqlSession
使用上面获得的SqlSessionFactory,先打开会话获取SqlSession,然后从SqlSession中获取UserMapper,最后调用UserMapper的方法,这里需要关注Mapper是怎么被代理的
1、调用DefaultSqlSessionFactory的openSession()方法,先获取执行器类型,然后通过类型打开Session
2、创建事务和执行器,构建SqlSession并返回
3、通过Class从SqlSession中获取Mapper,此过程及其重要。实际上是从Configuration中获取MapperProxyFactory 代理工厂,调用newInstance创建代理类MapperProxy<T>并返回
5、调用UserMapper的方法,实际上是调用代理对象方法,主要需要关注MapperProxy<T>的invoke方法
6、Mapp接口有实现类时直接invoke调用,没有实现类时先从methodCache中取,没取到构建MapperMethod并放入
7、按增删改查类型执行调用相应的执行,并包装结果返回