设计模式_代理模式_动态代理

我们两清 提交于 2019-12-17 03:02:10

转自: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。

JDK的Proxy方式实现的动态代理,目标对象必须要有接口,因为生成的代理对象要和目标对象实现相同的接口

 1 package cn.rocker.designpattern.proxy;
 2 
 3 import org.junit.Test;
 4 
 5 import java.lang.reflect.InvocationHandler;
 6 import java.lang.reflect.Method;
 7 import java.lang.reflect.Proxy;
 8 
 9 /**
10  * @author rocker
11  * @version V1.0
12  * @Description:
13  * @date 2018/5/6 19:59
14  */
15 public class JDKDynamicProxy {
16     @Test
17     public void test() {
18         //获得动态代理对象---在运行时,在内存中,动态地为RealRequest创建一个代理对象
19         Subject proxy = (Subject) Proxy.newProxyInstance(
20                 RealRequest.class.getClassLoader(),/*与目标对象相同的类加载器*/
21                 new RealRequest().getClass().getInterfaces()/*动态代理对象实现的接口的Class数组*/,
22                 new InvocationHandler() {
23                     @Override
24                     /**
25                      * proxy    生成的代理对象,此处为RealRequest的代理对象;  cn.rocker.designpattern.proxy.RealRequest@6d65d417
26                      *                                                    cn.rocker.designpattern.proxy.RealRequest@1f2eb71e
27                      * method   目标对象的方法,此处为RealRequest的方法:    public abstract void cn.rocker.designpattern.proxy.Subject.request()
28                      *                                                   public abstract void cn.rocker.designpattern.proxy.Subject.request2()
29                      * args     目标对象方法的参数,此处为:           null
30                      *                                              null
31                      */
32                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
33                         //目标对象的前处理
34                         System.out.println("i am the preHandler of the object...");
35 
36                         //这里通过反射来执行目标对象的方法
37                         Object invoke = method.invoke(new RealRequest(), args);
38 
39                         //目标对象的后处理
40                         System.out.println("i am the postHandler of the object...");
41                         return invoke;
42                     }
43                 });
44 
45         //动态生成的代理对象执行目标对象的相应方法(已经做了相应的前后处理)
46         proxy.request();
47         proxy.request2();
48     }
49 }

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!