image.png一、前言

  1. public static void main(String[] args) throws IOException {
  2. InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  3. SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  4. SqlSessionFactory factory = builder.build(in);
  5. SqlSession session = factory.openSession();
  6. //获得dao 的代理对象
  7. UserMapper userMapper = session.getMapper(UserMapper.class);
  8. User user = userMapper.queryById(21);
  9. System.out.println(user.toString());
  10. }

承接上一章 2、MyBatis Mapper生产与并发优化,在获取到代理mapper后,是如何执行接口中的方法的?
上一节写到了 “ UserMapper userMapper = session.getMapper(UserMapper.class); ”,这节将从 userMapper.queryById(21); 开始。
很明显这里的 userMapper 肯定是一个代理类,那代理类执行方法的时候,一定会执行到jdkProxy中的InvocationHandler 方法,首先我看看下这个代理类 MapperProxyFactory。
MapperProxyFactory 这个类在前一节已经提到过了,这里主要关注它的 newInstance 方法中使用的 MapperProxy(InvocationHandler的子类)。

为什么和 MapperProxyFactory 有关,可以回顾 addMappergetMapper,knownMappers 中存的values是MapperProxyFactory。

二、MapperProxy

MapperProxyFactory 中的方法如下,
image.png
MapperProxy 继承了接口 InvocationHandler,所以在执行代理方法时,实际上是执行的 MapperProxy 类中的 invoker方法—>MapperProxy的内部接口MapperMethodInvoker中的invoker方法,代码如下。
image.png
image.png
可以看到,最终调的是方法 MapperMethod 中的 execute 方法,接着根据sql的类型判断是SELCT,代码如下。
image.png
接着就进入了 sqlSession 类型,这里使用的是默认的 DefaultSqlSession

三、SqlSession

SqlSession用到了门面模式,封装了真正干活的Executor

1、selectOne

DefaultSqlSession 中的 selectOne方法内部使用的是 selectList 方法。
image.png

2、selectList

�首先获取这个接口对应的MappedStatement,MappedStatement中存放了例如xml文件的位置,mapper接口中方法的全类名,一级缓存的 key,等其他东西。image.png
接着进入 org.apache.ibatis.c.CachingExecutor#query方法,CachingExecutor 继承了接口 Executor,这是一个真正干活的类。

四、Executor

1、CachingExecutor 的 query

�接着上一节,进入 Executor(这里是CachingExecutor)的query方法之后,首先就是将 值(方法入参),和sql绑定,然后就是创建了 缓存 需要用到的key,如下。
image.png
继续进入 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);
} ……………._ �

image.png

2、BaseExecutor 的 query

接着继续进入query方法(BaseExecutor中的query)。

截止到这里,先用了 CachingExecutor 中的 query,然后使用了 BaseExecutor 中的 query,这里用到了什么设计模式? 装饰者模式:增强对象的行为。 代理模式:控制对象的行为。 这里用到的是装饰者模式。。。。

BaseExecutor 的 query 首先判断 一级缓存 localCache 中有没有值,每值就查DB
通过 queryFromDatabase 方法,开始准备对DB 进行操作了。
image.png

3、queryFromDatabase

image.png

4、doQuery

接着进入 doQuery,这里见到了我们熟悉的jdbc操作,获取Statement
image.png

5、StatementHandler

prepareStatement 方法进行参数的一些准备,然后就是handler.query方法,最后使用 PreparedStatement 的 execute执行sql,并返回结果。
image.png

五、结果集的封装

1、handleResultSets

image.pngimage.png
可以看到在handleResultSets方法中获取了restMap中的字段映射。
在这里进行了一些返回参数的组装。
细节。。。略

后续内容有时间可以专注视频 https://www.bilibili.com/video/BV1Z44y1b775?p=40&spm_id_from=pageDriver