动态代理模式的两种实现 —— jdk实现 VS cglib实现

关于动态代理模式里面有两种实现,一种是jdk实现,一种是cglib来实现
下面来整jdk来实现动态代理的Java实例。
jdk动态代理模式里面有个拦截器的概念,在jdk中,只要实现了InvocationHandler这个接口的类就是一个拦截器类
还使用了些反射的相关概念。
拦截器的概念不了解没关系,假如写了个请求到action,经过拦截器,然后才会到action。然后继续有之后的操作。
拦截器就像一个过滤网,一层层的过滤,只要满足一定条件,才能继续向后执行。
拦截器的作用:控制目标对象的目标方法的执行。

拦截器的具体操作步骤:
1.引入类:目标类和一些扩展方法相关的类。
2.赋值:调用构造函数给相关对象赋值
3.合并逻辑处理:在invoke方法中把所有的逻辑结合在一起。最终决定目标方法是否被调用。


下面看具体的代码实例:

目标接口类:

[java]  view plain  copy
  1. package com.lxk.designPattern.proxy.dynamicProxy.jdkDynamicProxy;  
  2.   
  3. /** 
  4.  * 目标接口: 
  5.  * 包含目标方法的声明 
  6.  */  
  7. public interface TargetInterface {  
  8.     /** 
  9.      * 目标方法 
  10.      */  
  11.     void business();  
  12. }  


目标类:
[java]  view plain  copy
  1. package com.lxk.designPattern.proxy.dynamicProxy.jdkDynamicProxy;  
  2.   
  3. /** 
  4.  * 被代理的类 
  5.  * 目标对象类 
  6.  * 实现目标接口. 
  7.  * 继而实现目标方法。 
  8.  */  
  9. public class TargetObject implements TargetInterface {  
  10.   
  11.     /** 
  12.      * 目标方法(即目标操作) 
  13.      */  
  14.     @Override  
  15.     public void business() {  
  16.         System.out.println("business");  
  17.     }  
  18.   
  19. }  

拦截器:

[java]  view plain  copy
  1. package com.lxk.designPattern.proxy.dynamicProxy.jdkDynamicProxy;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5.   
  6. /** 
  7.  * 动态代理-拦截器 
  8.  * <p> 
  9.  * Created by lxk on 2016/11/25 
  10.  */  
  11. public class MyInterceptor implements InvocationHandler {  
  12.     private Object target;//目标类  
  13.   
  14.     public MyInterceptor(Object target) {  
  15.         this.target = target;  
  16.     }  
  17.   
  18.     /** 
  19.      * args 目标方法的参数 
  20.      * method 目标方法 
  21.      */  
  22.     @Override  
  23.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  24.         System.out.println("aaaaa");//切面方法a();  
  25.         //。。。  
  26.         method.invoke(this.target, args);//调用目标类的目标方法  
  27.         //。。。  
  28.         System.out.println("bbbbb");//切面方法f();  
  29.         return null;  
  30.     }  
  31. }  

具体通过调用代理对象,来调用目标对象的目标方法的具体测试:

[java]  view plain  copy
  1. package com.lxk.designPattern.proxy.dynamicProxy.jdkDynamicProxy;  
  2.   
  3. import java.lang.reflect.Proxy;  
  4.   
  5. public class MainTest {  
  6.     public static void main(String[] args) {  
  7.         //目标对象  
  8.         TargetObject target = new TargetObject();  
  9.         //拦截器  
  10.         MyInterceptor myInterceptor = new MyInterceptor(target);  
  11.   
  12.         /* 
  13.          *  Proxy.newProxyInstance参数: 
  14.          *  1、目标类的类加载器 
  15.          *  2、目标类的所有的接口 
  16.          *  3、拦截器 
  17.          */  
  18.         //代理对象,调用系统方法自动生成  
  19.         TargetInterface proxyObj = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInterceptor);  
  20.         proxyObj.business();  
  21.     }  
  22. }  

看完代码实例,要 对这个动态代理进一步理解,要考虑到以下的问题。
1、代理对象是由谁产生的?

jvm产生的,不像上次的静态代理,我们自己得new个代理对象出来。
2、代理对象实现了什么接口?
实现的接口是目标对象实现的接口。同静态代理模式中代理对象实现的接口。那个继承关系图还是相同的。代理对象和目标对象都实现一个共同的接口。就是这个接口。所以Proxy.newProxyInstance()方法返回的类型就是这个接口类型。
3、代理对象的方法体是什么?
代理对象的方法体中的内容就是拦截器中invoke方法中的内容。所有代理对象的处理逻辑,控制是否执行目标对象的目标方法。都是在这个方法里面处理的。
4、拦截器中的invoke方法中的method参数是在什么时候赋值的?
在客户端,代理对象调用目标方法的时候,此实例中为:proxyObj.business();实际上进入的是拦截器中的invoke方法,这个时候
,拦截器中的invoke方法中的method参数会被赋值。

最后,为啥这个方式叫做jdk动态代理呢?
因为这个动态代理对象时用jdk的相关代码生成的,所以这个叫 jdk动态代理
后面的cglib动态代理,就是因为要用到cglib的jar包,所以才叫 cglib动态代理


了解了一个,那么另一个也就差不多啦。就继续往下看吧。

为什么要使用这个cglib来实现这个动态代理呢?因为spring框架要用。

具体的代码实现如下:

目标对象类:

[java]  view plain  copy
  1. package com.lxk.designPattern.proxy.dynamicProxy.cglbDynamicProxy;  
  2.   
  3. /** 
  4.  * 被代理的类 
  5.  * 目标对象类 
  6.  */  
  7. public class TargetObject {  
  8.   
  9.     /** 
  10.      * 目标方法(即目标操作) 
  11.      */  
  12.     public void business() {  
  13.         System.out.println("business");  
  14.     }  
  15.   
  16. }  

拦截器类:

[java]  view plain  copy
  1. package com.lxk.designPattern.proxy.dynamicProxy.cglbDynamicProxy;  
  2.   
  3. import net.sf.cglib.proxy.Enhancer;  
  4. import net.sf.cglib.proxy.MethodInterceptor;  
  5. import net.sf.cglib.proxy.MethodProxy;  
  6.   
  7. import java.lang.reflect.Method;  
  8.   
  9. /** 
  10.  * 动态代理-拦截器 
  11.  * <p> 
  12.  * Created by lxk on 2016/11/25 
  13.  */  
  14. public class MyInterceptor implements MethodInterceptor {  
  15.     private Object target;//目标类  
  16.   
  17.     public MyInterceptor(Object target) {  
  18.         this.target = target;  
  19.     }  
  20.   
  21.     /** 
  22.      * 返回代理对象 
  23.      * 具体实现,暂时先不追究。 
  24.      */  
  25.     public Object createProxy() {  
  26.         Enhancer enhancer = new Enhancer();  
  27.         enhancer.setCallback(this);//回调函数  拦截器  
  28.         //设置代理对象的父类,可以看到代理对象是目标对象的子类。所以这个接口类就可以省略了。  
  29.         enhancer.setSuperclass(this.target.getClass());  
  30.         return enhancer.create();  
  31.     }  
  32.   
  33.     /** 
  34.      * args 目标方法的参数 
  35.      * method 目标方法 
  36.      */  
  37.     @Override  
  38.     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {  
  39.         System.out.println("aaaaa");//切面方法a();  
  40.         //。。。  
  41.         method.invoke(this.target, objects);//调用目标类的目标方法  
  42.         //。。。  
  43.         System.out.println("bbbbb");//切面方法f();  
  44.         return null;  
  45.     }  
  46. }  

测试类:

[java]  view plain  copy
  1. package com.lxk.designPattern.proxy.dynamicProxy.cglbDynamicProxy;  
  2.   
  3. public class MainTest {  
  4.     public static void main(String[] args) {  
  5.         //目标对象  
  6.         TargetObject target = new TargetObject();  
  7.         //拦截器  
  8.         MyInterceptor myInterceptor = new MyInterceptor(target);  
  9.         //代理对象,调用cglib系统方法自动生成  
  10.         //注意:代理类是目标类的子类。  
  11.         TargetObject proxyObj = (TargetObject) myInterceptor.createProxy();  
  12.         proxyObj.business();  
  13.     }  
  14. }  

区别:

首先从文件数上来说,cglib比jdk实现的少了个接口类。因为cglib返回的代理对象是目标对象的子类。而jdk产生的代理对象和目标对象都实现了一个公共接口。

动态代理:

[java]  view plain  copy
  1. 动态代理分为两种:  
  2.    *  jdk的动态代理  
  3.       *  代理对象和目标对象实现了共同的接口  
  4.       *  拦截器必须实现InvocationHanlder接口  
  5.   
  6.    *  cglib的动态代理  
  7.       *  代理对象是目标对象的子类  
  8.       *  拦截器必须实现MethodInterceptor接口  
  9.       *  hibernate中session.load采用的是cglib实现的  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值