在平常我们写的 SSM 框架中, 定义了 Mapper 接口与 .xml 对应的 SQL 文件, 在 Service 层直接注入 xxxMapper 就可以了
也没有看到像 JDBC 操作数据库的操作, Mybatis 在中间是如何为我们省略下这些重复繁琐的操作呢
这里使用 Mybatis 源码中的测试类进行验证, 首先定义 Mapper 接口, 省事直接注解定义 SQL
这里使用 SqlSession 来获取 Mapper 操作数据库, 测试方法如下
#1 从 SqlSessionFactory 中打开一个 新的 SqlSession
#2 就存在一个疑问点, 定义的 AutoConstructorMapper 明明是个接口, 为什么可以实例化为对象?
#3 通过创建的对象调用类中具体的方法, 这里具体聊一下 #2 操作
SqlSession 是一个接口, 有一个 默认的实现类 DefaultSqlSession, 类中包含了 Configuration 属性
Mapper 接口的信息以及 .xml 中 SQL 语句是在 Mybatis 初始化时添加 到 Configuration 的 MapperRegistry 属性中的
#2 中的 getMapper 就是从 MapperRegistry 中获取 Mapper
看一下 MapperRegistry 的类属性都有什么
config 为 保持全局唯一 的 Configuration 对象引用
knownMappers 中 Key-Class 是 Mapper 对象, Value-MapperProxyFactory 是通过 Mapper 对象衍生出的 Mapper 代理工厂
再看一下 MapperProxyFactory 类的结构信息
mapperInterface 属性是 Mapper 对象的引用, methodCache 的 key 是 Mapper 中的方法, value 是 Mapper 解析对应 SQL 产生的 MapperMethod
📖 Mybatis 设计 methodCache 属性时使用到了 懒加载机制, 在初始化时不会增加对应 Method, 而是在 第一次调用时新增
MapperMethod 运行时数据如下, 比较容易理解
通过一个实际例子帮忙理解一下 MapperRegistry 类关系, Mapper 初始化第一次调用的对象状态, 可以看到 methodCache 容量为0
我们目前已经知道 MapperRegistry 的类关系, 回头继续看一下第二步的 MapperRegistry#getMapper() 处理步骤
核心处理在 MapperProxyFactory#newInstance() 方法中, 继续跟进
MapperProxy 继承了 InvocationHandler 接口, 通过 newInstance() 最终返回的是由 Java Proxy 动态代理返回的动态代理实现类
看到这里就清楚了步骤二中接口为什么能够被实例化, 返回的是 接口的动态代理实现类
微信搜索【源码兴趣圈】,关注龙台,回复【资料】领取涵盖 GO、Netty、SpringCLoud Alibaba、Seata、开发规范、面试宝典、数据结构等电子书 or 视频学习资料!