模拟mybatis代理

记录:
        理解与整理.
备注:模拟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;
  }
}

以上,感谢.

发布了183 篇原创文章 · 获赞 40 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/zhangbeizhen18/article/details/103735513