zoukankan      html  css  js  c++  java
  • 设计模式之Jdk动态代理

    什么是动态代理呢?
    就是在java的运行过程中,动态的生成的代理类。(为了更熟悉的了解动态代理,你必须先熟悉代理模式,可点击设计模式之代理模式 阅读)
    我们知道java属于解释型语言,是在运行过程中,寻找字节码文件从而实现类加载的。
    但是字节码文件并不需要一定是硬盘中的class文件,也可以是来自网络、数据库或者是直接生成的数据流。因此这就给虚拟机动态的生成代理类提供了可能。
    Java 1.3 正式引入,动态代理(Dynamic proxies)特性。
    前一篇文章我们已经知道Proxy是代理模式的核心,而动态代理就是在运行期间由虚拟机根据需要,动态的生成出这样一个代理类。
    我们可以直接看java的实现方法:

     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Proxy;
     3 
     4 public class DynamicProxyInvoker
     5 {
     6     public static void main(String[] args)
     7     {
     8         InvocationHandler proxyHandler = new SuperStarInvocationHandler("messi");
     9         ISuperStar superStarDynamicProxy = (ISuperStar) Proxy.newProxyInstance(ISuperStar.class.getClassLoader(), new Class<?>[]
    10         { ISuperStar.class }, proxyHandler);
    11         superStarDynamicProxy.signContract();
    12         superStarDynamicProxy.negotiate();
    13     }
    14 }
     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Method;
     3 
     4 public class SuperStarInvocationHandler implements InvocationHandler
     5 {
     6     private String proxyName;
     7     ISuperStar superStar;
     8     
     9     public SuperStarInvocationHandler(String startName)
    10     {
    11         this.proxyName = startName + "'s proxy";
    12         superStar = new SuperStar(startName);
    13     }
    14     
    15     @Override
    16     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    17     {
    18         System.out.println(proxyName + " signContract");
    19         Object object = method.invoke(superStar, args);
    20         return object;
    21     }
    22     
    23 }
     1 public interface ISuperStar
     2 {
     3     /**
     4      * 签约
     5      */
     6     public void signContract();
     7     
     8     /**
     9      * 谈判
    10      */
    11     public void negotiate();
    12 }
     1 public class SuperStar implements ISuperStar
     2 {
     3     private String starName;
     4     public SuperStar(String starName)
     5     {
     6         this.starName=starName;
     7     }
     8     
     9     @Override
    10     public void signContract()
    11     {
    12         System.out.println(starName+" signContract");
    13         // to do sth
    14         return;
    15     }
    16     
    17     @Override
    18     public void negotiate()
    19     {
    20         System.out.println(starName+" negotiate");
    21         // to do sth
    22         return;
    23     }
    24 }

    superStarDynamicProxy是由系统自动生成的,一个实现了接口ISuperStar的类。这个类并不存在于具体的实现。同时由于系统也不知道我们具体需要在代理类中做哪些的操作。
    因此需要我们自己提前安排好一个处理类SuperStarInvocationHandler。这个处理类中实现了代理类中是如何调用实现类中的方法的逻辑。
    他们的调用关系图是这样的:


           我们可以看到动态代理的结构图中,代理方并不会直接调用到被代理方,而是通过业务处理类来调用的。因此业务处理类需要保持一个被代理方的实例对象。(非强制)通过虚拟机主动生成动态代理类,我们可以发现,调用方和被调用方在代码实现阶段其实是断层的。并不存在依次的直接调用关系。因此耦合的概念会更浅。同时由于不再需要为像静态代理那样为每个类都实现一个代理类,因此以切面的形式加入代理层成为可能。这个我会在后续的文章中介绍。

           ps :有兴趣的同学可以在main方法中手动的将动态代理生成的代理方superStarDynamicProxy的字节码导入到一个.class文件中,然后反编译该文件。你就会发现,这个类其实就是被代理方所实现接口的一个适配类。其中的所有方法的实现都是调用业务处理类SuperStarInvocationHandler,再由业务处理类通过反射动态的调用到SuperStar类的。


    动态代理的不足

    1、早期由于jdk反射的性能有限,因此jdk的动态代理方式在性能上并不是很优越,但是随着jdk对于反射性能的优化,此处的性能损耗已经越来越小。
    2、从构建动态代理类的源码(有兴趣的同学也可以按照前文的形式反编译),或者是手动添加一个Instance Proxy的形式。
    我们可以发现,代理类其实是继承自Proxy的同时实现了接口。因此动态代理只能用来解决接口动态代理的场景,因为java是不允许集成自多个类的。此问题可以使用CGLIB来解决,有兴趣的同学可以自己看下,这个我会在后边的文章中介绍。

  • 相关阅读:
    关于hibernate中多对多关系
    选择排序
    Offer是否具有法律效力?
    textarea文本域宽度和高度(width、height)自己主动适应变化处理
    序列相关的趣题 之三
    windows的定时任务设置
    Maven pom.xml 配置详解
    PS 图像特效-非线性滤波器
    PS 滤镜算法原理——拼贴
    PS 滤镜算法原理——曝光过度
  • 原文地址:https://www.cnblogs.com/jilodream/p/10624940.html
Copyright © 2011-2022 走看看