转自:https://www.ibm.com/developerworks/cn/java/j-lo-proxy-pattern/index.html
动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。与静态处理类相比,动态类有诸多好处。首先,不需要为真实主题写一个形式上完全一样的封装类,假如主题接口中的方法很多,为每一个接口写一个代理方法也很麻烦。如果接口有变动,则真实主题和代理类都要修改,不利于系统维护;其次,使用一些动态代理的生成方法甚至可以在运行时制定代理类的执行逻辑,从而大大提升系统的灵活性。
动态代理类使用字节码动态生成加载技术,在运行时生成加载类。生成动态代理类的方法很多,如,JDK 自带的动态处理、CGLIB、Javassist 或者 ASM 库。JDK 的动态代理使用简单,它内置在 JDK 中,因此不需要引入第三方 Jar 包,但相对功能比较弱。CGLIB 和 Javassist 都是高级的字节码生成库,总体性能比 JDK 自带的动态代理好,而且功能十分强大。ASM 是低级的字节码生成工具,使用 ASM 已经近乎于在使用 Java bytecode 编程,对开发人员要求最高,当然,也是性能最好的一种动态代理生成工具。但 ASM 的使用很繁琐,而且性能也没有数量级的提升,与 CGLIB 等高级字节码生成工具相比,ASM 程序的维护性较差,如果不是在对性能有苛刻要求的场合,还是推荐 CGLIB 或者 Javassist。
以清单 1 所示代码中的 DBQueryProxy 为例,使用动态代理生成动态类,替换上例中的 DBQueryProxy。首先,使用 JDK 的动态代理生成代理对象。JDK 的动态代理需要实现一个处理方法调用的 Handler,用于实现代理方法的内部逻辑。
1 public class DBQueryHandler implements InvocationHandler { 2 IDBQuery realQuery = null;//定义主题接口 3 4 @Override 5 public Object invoke(Object proxy, Method method, Object[] args) 6 throws Throwable { 7 //如果第一次调用,生成真实主题 8 if (realQuery == null) { 9 realQuery = new DBQuery(); 10 } 11 //返回真实主题完成实际的操作 12 return realQuery.request(); 13 } 14 15 }
原文地址:https://www.cnblogs.com/rocker-pg/p/8999459.html