记录:
理解与整理.
备注:模拟mybatis代理只是记录而已20191227.
理解:
<1>.使用jdk代理,简化模拟mybatis代理实现
<2>.mybatis没有为接口去反射实现类
<3>.mybatis是在代理的执行方法中,使用代理方式设计了特有策略,根据接口的方法名,匹配对应配置文件中的sql.
模拟测试:
1.接口Topic
public interface Topic {
public void getInfo(String size);
public void getHeight();
}
2.代理工厂类
public class SimulationMapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, String> methodCache = new ConcurrentHashMap<>();
public SimulationMapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
@SuppressWarnings("unchecked")
protected T newInstance(SimulationMapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{ mapperInterface },mapperProxy);
}
public T newInstance(Map sqlSession) {
final SimulationMapperProxy<T> mapperProxy = new SimulationMapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
3.代理类
jdk动态代理需要实现InvocationHandler接口.
public class SimulationMapperProxy<T> implements InvocationHandler, Serializable {
private final Map sqlSession;
private final Class<T> mapperInterface;
private final Map<Method, String> methodCache;
public SimulationMapperProxy(Map sqlSession, Class<T> mapperInterface, Map<Method, String> methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("SimulationMapperProxy->invoke开始...");
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable t) {
;
}
}
final SimulationMapperMethod mapperMethod = cachedMapperMethod(method);
Object obj =mapperMethod.execute(sqlSession, args);
System.out.println("SimulationMapperProxy->invoke结束...");
return obj;
}
private SimulationMapperMethod cachedMapperMethod(Method method) {
SimulationMapperMethod mapperMethod = new SimulationMapperMethod(method);
return mapperMethod;
}
}
4.代理类需要代理的核心内容
public class SimulationMapperMethod {
private Method method;
public SimulationMapperMethod(Method method){
this.method = method;
}
public Object execute(Map sqlSession, Object[] args) {
System.out.println("SimulationMapperMethod->execute开始......");
System.out.println("在代理方法中并不实现接口类,而是根据接口调用的方法去匹配对应的配置文件中与之绑定的执行sql.");
System.out.println("接口方法:"+ this.method.getName());
System.out.println("匹配策略: 根据调用的方法匹配执行的sql.");
System.out.println("真正执行的sql:" + sqlSession.get(this.method.getName()));
System.out.println("SimulationMapperMethod->execute结束......");
return null;
}
}
5.测试类
init方法,模拟mybatis启动后,存储了加载的配置文件与接口方法对应关系.
main方法,测试入口.
public class TestMainDemo {
public static void main(String [] args){
System.out.println("测试开始......");
Map sqlSession = init();
System.out.println("");
SimulationMapperProxyFactory<Topic> zbMapperProxyFactory = new SimulationMapperProxyFactory(Topic.class);
Topic topic = zbMapperProxyFactory.newInstance(sqlSession);
System.out.println("开始调用topic.getInfo......");
topic.getInfo("G");
System.out.println("结束调用topic.getInfo......");
System.out.println("");
System.out.println("开始调用topic.getHeight......");
topic.getHeight();
System.out.println("结束调用topic.getHeight......");
System.out.println("");
System.out.println("测试结束......");
}
/**模拟:初始化接口与mapper中对应sql的关系*/
public static Map init(){
System.out.println("模拟:初始化接口与mapper中对应sql的关系");
Map sqlSession = new HashMap<String,String>();
String sql = "select * from tb_demo";
String sqlHeight = "select * from tb_height";
sqlSession.put("getInfo", sql);
sqlSession.put("getHeight", sqlHeight);
return sqlSession;
}
}
以上,感谢.