静态代理和动态代理对比

静态代理相对动态代理

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

            假如需要代理的主体类有很多个方法需要委托代理,那么代理类需要编写很多的实现方法,并且有时候在执行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的方法进行动态代理;

 

posted @ 2018-04-19 19:09  ╱、隐风っ九剑  阅读(492)  评论(0编辑  收藏  举报