文章目录
简介本文目的
本文意在学习理解mybatis工作原理,笔者参考了网上的各种文献由此写了这篇博客作为mybatis源码学习的开篇
思路
这章节我们会写一个很迷你的核心demo,我们都知道mybatis只需要我们在xml写一个特定格式的sql,然后和指定java接口进行关联,到时候调用这个接口自然就会去查sql。
很明显做到这一点的方式只有一个,那就是代理,如下图所示,我们只需将对应的要进行查sql的接口交给代理来创建,后续我们使用这个接口的时候,代理就会帮忙完成调用sql的操作。
类图
所以我们要创建一个sql查询逻辑代理类,但是这个代理我们不想要用户自己创建,所以我们搞一个工厂封装这个逻辑。
编码
代理类
package cn.zsy.mybatis.binding;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
public class MapperProxy<T> implements InvocationHandler, Serializable {
/**
* serialVersionUID 称为序列化版本号,这个多用于实现了Serializable的类中,适用场景是类的序列化,当我们没有定义这个值得时候虚拟机会根据类的属性生成一个独一无二的序列化版本号。
* 在反序列化时,虚拟机会根据该变量值去寻找,如果找的到该值反序列化成功,找不到该值反序列化失败。
* 但是这样有一个劣势,类一旦序列化后我们就不能再修改该类的属性,一旦修改,序列化ID会变化,这会导致后续的反序列化失败。
* 如果我们手动定义一个序列化ID的话,虚拟机就不会进行计算了。
*/
private static final long serialVersionUID = -6424540398559729838L;
private Map<String, String> sqlSession;
private Class<T> mapperInterface;
public MapperProxy(Map<String, String> sqlSession, Class<T> mapperInterface) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
return "mybaits代理调用 :"+mapperInterface.getName() + "." + method.getName()+"****" + sqlSession.get(mapperInterface.getName() + "." + method.getName());
}
}
创建代理的工厂
public class MapperProxyFactory<T> {
/**
* 被代理的dao层接口
*/
private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public T newInstance(Map<String,String> sqlSession){
final MapperProxy<T> mapperProxy=new MapperProxy<T>(sqlSession,mapperInterface);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),new Class[]{mapperInterface},mapperProxy);
}
}
测试
测试接口
public interface IUserDao {
String queryUserName(String uId);
Integer queryUserAge(String uId);
}
测试类
public class MainTest {
@Test
public void test_MapperProxyFactory(){
MapperProxyFactory<IUserDao> proxyFactory=new MapperProxyFactory<IUserDao>(IUserDao.class);
HashMap<String, String> sqlSession = new HashMap<String, String>();
sqlSession.put("cn.zsy.mybatis.test.dao.IUserDao.queryUserName","select name from user where id=?");
IUserDao iUserDao = proxyFactory.newInstance(sqlSession);
System.out.println(iUserDao.queryUserName("1"));//mybaits代理调用 :cn.zsy.mybatis.test.dao.IUserDao.queryUserName****select name from user where id=?
}
}
参考文献
《Mybatis 手撸专栏》第2章:创建简单的映射器代理工厂