深入理解 Java 动态代理机制

 Java 有两种代理方式,一种是静态代理,另一种是动态代理。对于静态代理,其实就是通过依赖注入,对对象进行封装,不让外部知道实现的细节。很多 API 就是通过这种形式来封装的。

代理模式结构图(图片来自《大话设计模式》)

下面看下两者在概念上的解释:

静态代理

  • 静态代理类:由程序员创建或者由第三方工具生成,再进行编译;在程序运行之前,代理类的.class文件已经存在了。

  • 静态代理类通常只代理一个类。

  • 静态代理事先知道要代理的是什么。

动态代理

  • 动态代理类:在程序运行时,通过反射机制动态生成。

  • 动态代理类通常代理接口下的所有类。

  • 动态代理事先不知道要代理的是什么,只有在运行的时候才能确定。

  • 动态代理的调用处理程序必须事先InvocationHandler接口,及使用Proxy类中的newProxyInstance方法动态的创建代理类。

  • Java动态代理只能代理接口,要代理类需要使用第三方的CLIGB等类库。

动态代理的好处

Java动态代理的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(甚至不去执行这个方法就可以)。此外,也可以减少代码量,如果采用静态代理,类的方法比较多的时候,得手写大量代码。

动态代理实例

静态代理的实例这里就不说了,比较简单。在 java 的 java.lang.reflect 包下提供了一个 Proxy 类和一个 InvocationHandler 接口,通过这个类和这个接口可以生成 JDK 动态代理类和动态代理对象。下面讲讲动态代理的实现。

先定义一个接口:

复制代码
public interface Person {     void setName(String name); }
复制代码

再定义一个学生 Student 类来实现 Person 接口,每一个学生都有一个自己的名字:

复制代码
public class Student implements Person {          private String mName;      public Student(String name) {         mName = name;     }      public void setName(String name) {         mName = name;     } }
复制代码

 Student 类中,定义了一个私有变量 mName,用来表示 Student 的名字。接下去定义一个代理 handler,就是用来帮我们处理代理的 :

复制代码
public class PersonHandler<T> implements InvocationHandler {     // 代理的目标对象    private T mTarget;      public PersonHandler(T target) {         mTarget = target;     }      @Override     public Object invoke(Object o, Method method, Object[] objects) throws Throwable {         // 调用开始前的操作        ProxyUtil.start();         // 调用方法,通过反射的形式来调用 mTarget 的 method         Object result = method.invoke(mTarget, objects);         // 打印改名前的名字        ProxyUtil.log(objects[0].toString());         // 调用结束后的操作        ProxyUtil.finish();         <
                    
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信