静态代理相对动态代理
缺点:每当你需要代理的方法越多的时候,那么你需要编写的重复代码就越多;
假如需要代理的主体类有很多个方法需要委托代理,那么代理类需要编写很多的实现方法,并且有时候在执行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的方法进行动态代理;