java动态代理是一个挺有意思的东西,他有时候可以被使用的很灵活。像rpc的调用,调用方只是定义的一个接口,动态代理让他匹配上对应的不同接口;mybatis内部的实现,编码时,只是实现了mapper层的接口和sql的xml的配置,动态代理把他们连起来。记得之前在一家公司,他们使用thrift做rpc的解决方案,每个项目都得管理thrift的连接和关闭,代码考来考去,在spring下还得不断new对象。后来参照mybatis的实现方式,使用动态代理,做成spring注入的方式,方便很多,程序员只需要加些配置就好了。
 
     先来一个动态代理的简单实例:
/**
* Created by sten on 7/12/16.
*/
public interface Person { void eat() ;
} /**
* Created by sten on 7/12/16.
*/
public class Chinese implements Person { @Override
public void eat() {
System.out.print("eat fish.");
}
} /**
* Created by sten on 7/12/16.
*/
public class InvocationTest implements InvocationHandler { private Person person ; public InvocationTest(Person person) {
this.person = person ;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(person, args);
}
} /**
* Created by sten on 7/12/16.
*/
public class Main { public static void main(String[] args) { Chinese chinese = new Chinese() ; Person person = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),
new Class[]{Person.class},
new InvocationTest(chinese)); person.eat();
} }
 
这是一般动态代理的范式,Chinese代理Person的实现,接口person每个方法的调用,实际执行的方法是InvocationTest.invoke, 当然,还有动态代理还有其他实现方式。
 
这里实现简单实现下mybatis的动态代理:
 
假设解析完mapper和xml,知道每个mapper的方法对应的sql了,通过类名和方法名,就可以执行sql
 

/**
* Created by sten on 7/12/16.
*/
public class SqlMap { private Map<String, String> map = new HashedMap() ; public SqlMap() {
map.put("Class1.method1","select sql1") ;
map.put("Class1.method2","delete sql1") ;
map.put("Class1.method3","update sql1") ;
map.put("Class1.method4","insert sql1") ;
map.put("Class2.method1","select sql2") ;
map.put("Class2.method2","delete sql2") ;
map.put("Class2.method3","update sql2") ;
map.put("Class2.method4","insert sql2") ;
} public String getSql(String classNameMethodName) {
return map.get(classNameMethodName) ;
} }
 
假设定义的一个mapper
 
/**
* Created by sten on 7/12/16.
*/
public interface Class1 { String method1() ; String method2() ; String method3() ; String method4() ;
}

 
InvocationHandler的实现
 
/**
* Created by sten on 7/12/16.
*/
public class InvocationSql implements InvocationHandler { private Class interfaceObject ; private SqlMap sqlMap ; public InvocationSql(Class interfaceObject, SqlMap sqlMap) {
this.interfaceObject = interfaceObject ;
this.sqlMap = sqlMap ;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String key = interfaceObject.getClass().getName() + "." + method.getName() ;
String value = sqlMap.getSql(key) ; return value ;
}
}

 
根据mapper接口生成对象
 
/**
* Created by sten on 7/12/16.
*/
public class TargetProxy<T> { public T getTarget(Class<T> interfaceObject, SqlMap sqlMap) { InvocationSql invocationSql = new InvocationSql(interfaceObject, sqlMap) ; return (T)newProxyInstance(interfaceObject.getClassLoader(),new Class[] {interfaceObject},
invocationSql) ;
} }

 
执行生成的对象

/**
* Created by sten on 7/12/16.
*/
public class Bitis { public static void main(String[] args) { TargetProxy targetProxy = new TargetProxy() ; Class1 class1 = (Class1) targetProxy.getTarget(Class1.class, new SqlMap()); class1.method1() ;
} }
 
 
 
 
 

最新文章

  1. 开始学nodejs —— 调试篇
  2. ORCALE复制表结构
  3. javascript --- 设计模式之构造函数模式
  4. SRS(simple-rtmp-server)
  5. 删除重复的字符(给一个字符串,删除连续重复的字符,要求时间复杂度为O(1)……)
  6. luarocks install with lua5.1 and luajit to install lapis
  7. jquery中each()函数
  8. go语言值得学习的开源项目推荐
  9. ios-王云鹤 把UIdatePicker 嵌入到 UIActionSheet中
  10. 清明培训 清北学堂 DAY1
  11. Fundebug能够捕获这些BUG
  12. 大数据及Hadoop的概述
  13. 15个最佳的 JavaScript 表单验证库
  14. Win10安装CAD2006
  15. javascript的常用事件
  16. .NET中制做对象的副本(二)继承对象之间的数据拷贝
  17. redhat vim编辑器永久添加行号及搜索
  18. ELK 日志查询分析nginx日志
  19. Dapper 嵌套对象查询
  20. react篇章-React State(状态)-组件都是真正隔离的

热门文章

  1. KMP --关于cogs1570 乌力波
  2. fzu1704(高斯消元法解异或方程组+高精度输出)
  3. [CF707D]Persistent Bookcase_主席树_bitset
  4. confluence导出PDF格式文件不显示中文解决
  5. mysql非主键提示key2 检查索引是否设定为唯一
  6. 编写shell脚本实现对虚拟机cpu、内存、磁盘监控机制
  7. (十二)springMvc 处理图片,视频等文件的上传
  8. 【模板】C++高精度加法
  9. redis键空间通知(keyspace notification)
  10. Java基础之IO和NIO补完