mybaits动态代理之最小demo实现
之前介绍jdbc时,我们把sql语句硬编码到代码中实现对数据库的操作(原文链接:一文读懂JDBC
),如果实际项目中这样使用会造成维护的复杂性。那么是否可以通过配置的方式来实现呢?
mybaits提供了一种动态代理的方式,将sql在xml文件中进行维护,同时建立接口的映射关系,在调用接口中的方法时,通过sqlSession来调用jdbc进行数据库操作。
整体来说包含以下子系统:
-
建立接口代理框架,调用接口方法时执行代理类的方法。
-
代理类使用SqlSessionFactory与数据库进行通信
xml解析为MappedStatement,并加入SqlSessionFactory缓存。
本文省略掉xml具体解析过程和SqlSession内容,主要研究接口代理映射到xml中的关系(参考mysbiats中bingding包)。
通过一个小demo来了解一下实现过程 :
我们建立一个xml文件BindingMapper.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.bingding.BindingMapper">
<select id="select">
select * from db;
</select>
<insert id="insert">
insert into db values('name','age')
</insert>
</mapper>
和一个接口BindingMapper.java
:
public interface BindingMapper {
Object select();
int insert();
}
最终,希望通过调用接口的方法,得到sql语句的输出。
最小实现类图如下:
使用入口在于通过MapperProxyFactory来创建一个接口的代理对象,执行接口的方法时会进入代理对象的invoke()
方法。
类说明如下:
-
SqlSessionFactory对象,用于对数据库进行操作,这里我们简化为输出sql语句,创建过程:
- 首先读取xml文件,并解析
- 使用Configuration来缓存xml解析后的结果(MappedStatement) ,configuration通过聚合在SqlSessionFactory对象中传递给具体的执行类。
-
MapperProxy代理对象,执行接口的方法映射到该对象的invoke()方法
-
MapperMethod对象,执行具体的处理
注:关于sql的语句的处理以及注解的使用本文没有涉及。
首先根据动态代理写出我们的接口代理框架,其中包含
- MapperProxyFactory,用于生成MapperProxy,通过传入接口的class对象 来 创建MapperProxyFactory实例
public class MapperProxyFactroy<T> {
private final Class<T> mapperInterface;
// 缓存
private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<> ();
public MapperProxyFactroy(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public T newInstance(SqlSessionFactory sqlSessionFactory){
final MapperProxy<T> mapperProxy = new MapperProxy<