• 静态代理和动态代理对比


    静态代理相对动态代理

      缺点:每当你需要代理的方法越多的时候,那么你需要编写的重复代码就越多;

                假如需要代理的主体类有很多个方法需要委托代理,那么代理类需要编写很多的实现方法,并且有时候在执行Proxy代理的Before、Afte业务逻辑r操作代码都是相同的,这样就尴尬了,重复的代码太多,没有营养,这时候就出现了动态代理的概念

    1、编写一个接口Subject

     1 package com.neusoft.pattern.staticProxy;
     2 
     3 /**
     4  * <p>Title:</p>
     5  * <p>Description:代理接口对象</p>
     6  * <p>Copyright:Copyright (c) 2018</p>
     7  * <p>Company:东软集团股份有限公司</p>
     8  * CreateDate:2018/4/19 0019 下午 18:00
     9  * Author:段美林[duanml@neusoft.com]
    10  * Version:1.0
    11  */
    12 public interface Subject {
    13 
    14     void request();
    15 
    16     void response();
    17 }

    2、编写一个实现了接口的被代理类 RealSubject

     1 package com.neusoft.pattern.staticProxy;
     2 
     3 /**
     4  * <p>Title:</p>
     5  * <p>Description:需要被代理实现的主体类</p>
     6  * <p>Copyright:Copyright (c) 2018</p>
     7  * <p>Company:东软集团股份有限公司</p>
     8  * CreateDate:2018/4/19 0019 下午 18:14
     9  * Author:段美林[duanml@neusoft.com]
    10  * Version:1.0
    11  */
    12 public class RealSubject implements Subject {
    13 
    14 
    15     @Override
    16     public void request() {
    17         System.out.println("real subject execute request=========");
    18     }
    19 
    20     @Override
    21     public void response() {
    22         System.out.println("real subject execute response=========");
    23     }
    24 }

    *********下面分别采用动态代理的方式实现 对主体类的代理*************************

    *********动态代理:实现方式有两种分别如下:***********************

    第一种方式:基于接口的代理实现方式;  ----------> 标准的JDK动态代理;  有如下几个要点

        a、基于Java.lang.reflect.Proxy 来动态生成被代理的主体类;

        b、必须实现接口:InvocationHandler接口;

        c、只能基于接口进行动态代理,即被代理类必须是基于接口的编程类,否则不能进行动态代理;

        d、必须拥有被代理类的引用 RealSubject,并且通过构造方法传入引用;

        e、利用JAVA反射 method.invoke(realSubject,args) 执行被代理类的本身业务逻辑;

    3、编写JDK动态代理类的实现 JDKProxySubject

     1 package com.neusoft.pattern.JDKProxy;
     2 
     3 import com.neusoft.pattern.staticProxy.RealSubject;
     4 
     5 import java.lang.reflect.InvocationHandler;
     6 import java.lang.reflect.Method;
     7 
     8 /**
     9  * <p>Title:</p>
    10  * <p>Description:JDK的动态代理实现方式</p>
    11  * <p>Copyright:Copyright (c) 2018</p>
    12  * <p>Company:东软集团股份有限公司</p>
    13  * CreateDate:2018/4/19 0019 下午 19:13
    14  * Author:段美林[duanml@neusoft.com]
    15  * Version:1.0
    16  */
    17 public class JDKProxySubject implements InvocationHandler{
    18 
    19     private RealSubject realSubject;
    20 
    21     public JDKProxySubject(RealSubject realSubject) {
    22         this.realSubject = realSubject;
    23     }
    24 
    25     @Override
    26     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    27 
    28         System.out.println("JDK动态代理运行,执行:Before " + method.getName() + " is invoked~~~~~~");
    29 
    30         Object result = null;
    31 
    32         try {
    33             result = method.invoke(realSubject,args);
    34         } catch (Exception e) {
    35             System.out.println("ex:"+e.getMessage());
    36             throw e;
    37         } finally {
    38             System.out.println("JDK动态代理运行,执行:After " + method.getName() + " is invoked~~~~~~");
    39         }
    40         return result;
    41     }
    42 }

    编写客户端调用类 JDKClient

     1 package com.neusoft.pattern.JDKProxy;
     2 
     3 import com.neusoft.pattern.staticProxy.RealSubject;
     4 import com.neusoft.pattern.staticProxy.Subject;
     5 
     6 import java.lang.reflect.Proxy;
     7 
     8 /**
     9  * <p>Title:</p>
    10  * <p>Description:JDK动态代理类的客户端</p>
    11  * <p>Copyright:Copyright (c) 2018</p>
    12  * <p>Company:东软集团股份有限公司</p>
    13  * CreateDate:2018/4/19 0019 下午 19:23
    14  * Author:段美林[duanml@neusoft.com]
    15  * Version:1.0
    16  */
    17 public class JDKClient {
    18 
    19     public static void main(String[] args) {
    20 
    21         Subject subject = (Subject) Proxy.newProxyInstance(JDKClient.class.getClassLoader(),
    22                 new Class[]{Subject.class}, new JDKProxySubject(new RealSubject()));
    23 
    24         subject.response();
    25     }
    26 }

    执行结果为:

    第二种方式:基于继承的代理实现方式; -----------> CgLib的第三方架构实现;有如下几个要点:

    a、必须实现接口 MethodInterceptor  ;

    b、重写intercept()方法,实现嵌入业务逻辑代码;

    c、利用JAVA反射 methodProxy.invokeSuper(object,args)  执行被代理类的本身业务逻辑;

    d、客户端调用类采用 Enhancer  类来操作设置相应的关系;

    4、编写CgLibdon动态代理类的实现:CgLibProxySubject

     1 package com.neusoft.pattern.CgLibProxy;
     2 
     3 import org.springframework.cglib.proxy.MethodInterceptor;
     4 import org.springframework.cglib.proxy.MethodProxy;
     5 
     6 import java.lang.reflect.Method;
     7 
     8 public class CgLibProxySubject implements MethodInterceptor{
     9 
    10 
    11     @Override
    12     public Object intercept(Object object, Method method, Object[] args,
    13                             MethodProxy methodProxy) throws Throwable {
    14 
    15         System.out.println("CgLib动态代理运行,执行:Before " + method.getName() + " is invoked~~~~~~");
    16         Object result = null;
    17         try {
    18             result = methodProxy.invokeSuper(object,args);
    19         } catch (Exception e) {
    20             System.out.println("ex:"+e.getMessage());
    21             throw e;
    22         } finally {
    23             System.out.println("CgLib动态代理运行,执行:After " + method.getName() + " is invoked~~~~~~");
    24         }
    25         return result;
    26     }
    27 }

     编写客户端调用类:CgLibClient

     1 package com.neusoft.pattern.CgLibProxy;
     2 
     3 import com.neusoft.pattern.staticProxy.RealSubject;
     4 import com.neusoft.pattern.staticProxy.Subject;
     5 import org.springframework.cglib.proxy.Enhancer;
     6 
     7 public class CgLibClient {
     8 
     9     public static void main(String[] args) {
    10         Enhancer enhancer = new Enhancer();
    11         enhancer.setSuperclass(RealSubject.class);
    12         enhancer.setCallback(new CgLibProxySubject());
    13         Subject subject = (Subject) enhancer.create();
    14         subject.request();
    15 
    16     }
    17 }

    执行运行结果如下:

    写在最后:  JDK动态代理和CgLib动态代理对比

    1、JDK动态代理只能针对实现了某个接口的类,然后对这个接口方法进行动态代理;

    2、CgLib动态代理是基于类继承的方式来实现代理,无法对static、final类进行动态代理;

    3、CgLib动态代理是基于类继承的方式来实现代理,无法对private、static方法进行动态代理;

    4、JDK动态代理是基于接口实现的代理,因为接口中不能申明为private类型的方法,所以JDK也不能对private的方法进行动态代理;

  • 相关阅读:
    理解C语言中指针常量和常量指针区别!不要再搞混了~
    哪座城市可以安放程序员的灵魂,一线城市与二三线城市该如何择别?
    Linux 之父如何定义 "Linux" !主要想让黑客、计算机学生使用,学习和享受!
    程序员的凡尔赛文学!作为低调人群的程序员,“凡”起来又是怎样的一番景象呢?
    40个Java集合面试问题和答案
    从关系型数据库到非关系型数据库
    redis安装报错
    redis简介
    不满足依赖关系
    EL表达式中引用隐式变量
  • 原文地址:https://www.cnblogs.com/yinfengjiujian/p/8885463.html
Copyright © 2020-2023  润新知