一、前言
public static void main(String[] args) throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//获得dao 的代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.queryById(21);
System.out.println(user.toString());
}
承接上一章 2、MyBatis Mapper生产与并发优化,在获取到代理mapper后,是如何执行接口中的方法的?
上一节写到了 “ UserMapper userMapper = session.getMapper(UserMapper.class); ”,这节将从 userMapper.queryById(21); 开始。
很明显这里的 userMapper 肯定是一个代理类,那代理类执行方法的时候,一定会执行到jdkProxy中的InvocationHandler 方法,首先我看看下这个代理类 MapperProxyFactory。
MapperProxyFactory 这个类在前一节已经提到过了,这里主要关注它的 newInstance 方法中使用的 MapperProxy(InvocationHandler的子类)。
为什么和 MapperProxyFactory 有关,可以回顾 addMapper 和 getMapper,knownMappers 中存的values是MapperProxyFactory。
二、MapperProxy
MapperProxyFactory 中的方法如下,
MapperProxy 继承了接口 InvocationHandler,所以在执行代理方法时,实际上是执行的 MapperProxy 类中的 invoker方法—>MapperProxy的内部接口MapperMethodInvoker中的invoker方法,代码如下。
可以看到,最终调的是方法 MapperMethod 中的 execute 方法,接着根据sql的类型判断是SELCT,代码如下。
接着就进入了 sqlSession 类型,这里使用的是默认的 DefaultSqlSession
三、SqlSession
SqlSession用到了门面模式,封装了真正干活的Executor
1、selectOne
DefaultSqlSession 中的 selectOne方法内部使用的是 selectList 方法。
2、selectList
�首先获取这个接口对应的MappedStatement,MappedStatement中存放了例如xml文件的位置,mapper接口中方法的全类名,一级缓存的 key,等其他东西。
接着进入 org.apache.ibatis.c.CachingExecutor#query方法,CachingExecutor 继承了接口 Executor,这是一个真正干活的类。
四、Executor
1、CachingExecutor 的 query
�接着上一节,进入 Executor(这里是CachingExecutor)的query方法之后,首先就是将 值(方法入参),和sql绑定,然后就是创建了 缓存 需要用到的key,如下。
继续进入 query 方法,注意 这里是二级缓存
// 用于存储二级缓存 private final TransactionalCacheManager tcm = new TransactionalCacheManager();
public class TransactionalCacheManager {
_private final Map<_Cache, TransactionalCache_> transactionalCaches = new HashMap<>();__ _public Object getObject(Cache cache, CacheKey key) {
return getTransactionalCache(cache).getObject(key);
} ……………._ �
2、BaseExecutor 的 query
接着继续进入query方法(BaseExecutor中的query)。
截止到这里,先用了 CachingExecutor 中的 query,然后使用了 BaseExecutor 中的 query,这里用到了什么设计模式? 装饰者模式:增强对象的行为。 代理模式:控制对象的行为。 这里用到的是装饰者模式。。。。
BaseExecutor 的 query 首先判断 一级缓存 localCache 中有没有值,每值就查DB
通过 queryFromDatabase 方法,开始准备对DB 进行操作了。
3、queryFromDatabase
4、doQuery
接着进入 doQuery,这里见到了我们熟悉的jdbc操作,获取Statement
5、StatementHandler
prepareStatement 方法进行参数的一些准备,然后就是handler.query方法,最后使用 PreparedStatement 的 execute执行sql,并返回结果。
五、结果集的封装
1、handleResultSets
�
可以看到在handleResultSets方法中获取了restMap中的字段映射。
在这里进行了一些返回参数的组装。
细节。。。略
后续内容有时间可以专注视频 https://www.bilibili.com/video/BV1Z44y1b775?p=40&spm_id_from=pageDriver
�