博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring 中JDKProxy和CGlibProxy的区别
阅读量:7073 次
发布时间:2019-06-28

本文共 6635 字,大约阅读时间需要 22 分钟。

环境要求

 

 

spring对AOP的支持

*如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

* 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
*如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

如何强制使用CGLIB实现AOP?
 * 添加CGLIB库,SPRING_HOME/cglib/*.jar
 * 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
 
JDK动态代理和CGLIB字节码生成的区别?
 * JDK动态代理只能对实现了接口的类生成代理,而不能针对类
 * CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
   因为是继承,所以该类或方法最好不要声明成final 

 

下面就看看怎么用JDK、CGLib的方式实现动态代理

 

首先先看下

 

UserManager接口

[java]
  1. package com.macower.spring.proxy;  
  2.   
  3. public interface UserManager {  
  4.     public void addUser(String id, String password);  
  5.     public void delUser(String id);  
  6. }  

package com.macower.spring.proxy; public interface UserManager { public void addUser(String id, String password); public void delUser(String id); }

 

接下来是其实现类  UserManagerImpl

 

[java]
  1. package com.macower.spring.proxy;  
  2.   
  3. public class UserManagerImpl implements UserManager {  
  4.   
  5.     public void addUser(String id, String password) {  
  6.         System.out.println(".: 掉用了UserManagerImpl.addUser()方法! ");  
  7.   
  8.     }  
  9.   
  10.     public void delUser(String id) {  
  11.         System.out.println(".: 掉用了UserManagerImpl.delUser()方法! ");  
  12.   
  13.     }  
  14. }  

package com.macower.spring.proxy; public class UserManagerImpl implements UserManager { public void addUser(String id, String password) { System.out.println(".: 掉用了UserManagerImpl.addUser()方法! "); } public void delUser(String id) { System.out.println(".: 掉用了UserManagerImpl.delUser()方法! "); } }

 

 

JDK动态代理类

 

[java]
  1. package com.macower.spring.proxy;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. /** 
  6.  *  
  7.  * JDK动态代理类 
  8.  * @author Macower 
  9.  * 
  10.  */  
  11. public class JDKProxy implements InvocationHandler {  
  12.   
  13.     private Object targetObject;//需要代理的目标对象   
  14.   
  15.     public Object newProxy(Object targetObject) {
    //将目标对象传入进行代理   
  16.         this.targetObject = targetObject;   
  17.         return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
  18.                 targetObject.getClass().getInterfaces(), this);//返回代理对象   
  19.     }  
  20.   
  21.     public Object invoke(Object proxy, Method method, Object[] args)//invoke方法   
  22.             throws Throwable {  
  23.         checkPopedom();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限   
  24.         Object ret = null;      // 设置方法的返回值   
  25.         ret  = method.invoke(targetObject, args);       //调用invoke方法,ret存储该方法的返回值   
  26.         return ret;  
  27.     }  
  28.   
  29.     private void checkPopedom() {
    //模拟检查权限的例子   
  30.         System.out.println(".:检查权限  checkPopedom()!");  
  31.     }  
  32. }  

package com.macower.spring.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * * JDK动态代理类 * @author Macower * */ public class JDKProxy implements InvocationHandler { private Object targetObject;//需要代理的目标对象 public Object newProxy(Object targetObject) {//将目标对象传入进行代理 this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);//返回代理对象 } public Object invoke(Object proxy, Method method, Object[] args)//invoke方法 throws Throwable { checkPopedom();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限 Object ret = null; // 设置方法的返回值 ret = method.invoke(targetObject, args); //调用invoke方法,ret存储该方法的返回值 return ret; } private void checkPopedom() {//模拟检查权限的例子 System.out.println(".:检查权限 checkPopedom()!"); } }

 

CGLibProxy动态代理类

 

 

[java]
  1. package com.macower.spring.proxy;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import net.sf.cglib.proxy.Enhancer;  
  6. import net.sf.cglib.proxy.MethodInterceptor;  
  7. import net.sf.cglib.proxy.MethodProxy;  
  8.   
  9. /** 
  10.  * CGLibProxy动态代理类的实例 
  11.  *  
  12.  * @author Macower 
  13.  *  
  14.  */  
  15. public class CGLibProxy implements MethodInterceptor {  
  16.   
  17.     private Object targetObject;// CGLib需要代理的目标对象   
  18.   
  19.     public Object createProxyObject(Object obj) {  
  20.         this.targetObject = obj;  
  21.         Enhancer enhancer = new Enhancer();  
  22.         enhancer.setSuperclass(obj.getClass());  
  23.         enhancer.setCallback(this);  
  24.         Object proxyObj = enhancer.create();  
  25.         return proxyObj;// 返回代理对象   
  26.     }  
  27.   
  28.     public Object intercept(Object proxy, Method method, Object[] args,  
  29.             MethodProxy methodProxy) throws Throwable {  
  30.         Object obj = null;  
  31.         if ("addUser".equals(method.getName())) {
    // 过滤方法   
  32.             checkPopedom();// 检查权限   
  33.         }  
  34.         obj = method.invoke(targetObject, args);  
  35.         return obj;  
  36.     }  
  37.   
  38.     private void checkPopedom() {  
  39.         System.out.println(".:检查权限  checkPopedom()!");  
  40.     }  
  41. }  

package com.macower.spring.proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * CGLibProxy动态代理类的实例 * * @author Macower * */ public class CGLibProxy implements MethodInterceptor { private Object targetObject;// CGLib需要代理的目标对象 public Object createProxyObject(Object obj) { this.targetObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); enhancer.setCallback(this); Object proxyObj = enhancer.create(); return proxyObj;// 返回代理对象 } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; if ("addUser".equals(method.getName())) {// 过滤方法 checkPopedom();// 检查权限 } obj = method.invoke(targetObject, args); return obj; } private void checkPopedom() { System.out.println(".:检查权限 checkPopedom()!"); } }

 

 

下面来测试下

[java]
  1. package com.macower.spring.proxy;  
  2.   
  3. public class Client {  
  4.   
  5.     public static void main(String[] args) {  
  6.   
  7.         UserManager userManager = (UserManager) new CGLibProxy()  
  8.                 .createProxyObject(new UserManagerImpl());  
  9.         System.out.println("-----------CGLibProxy-------------");  
  10.         userManager.addUser("Macower""root");  
  11.         System.out.println("-----------JDKProxy-------------");  
  12.         JDKProxy jdkPrpxy = new JDKProxy();  
  13.         UserManager userManagerJDK = (UserManager) jdkPrpxy  
  14.                 .newProxy(new UserManagerImpl());  
  15.         userManagerJDK.addUser("Macower""root");  
  16.     }  
  17.   
  18. }  

package com.macower.spring.proxy; public class Client { public static void main(String[] args) { UserManager userManager = (UserManager) new CGLibProxy() .createProxyObject(new UserManagerImpl()); System.out.println("-----------CGLibProxy-------------"); userManager.addUser("Macower", "root"); System.out.println("-----------JDKProxy-------------"); JDKProxy jdkPrpxy = new JDKProxy(); UserManager userManagerJDK = (UserManager) jdkPrpxy .newProxy(new UserManagerImpl()); userManagerJDK.addUser("Macower", "root"); } }

 

 

执行结果是:

[java]
  1. -----------CGLibProxy-------------  
  2. .:检查权限  checkPopedom()!  
  3. .: 掉用了UserManagerImpl.addUser()方法!   
  4. -----------JDKProxy-------------  
  5. .:检查权限  checkPopedom()!  
  6. .: 掉用了UserManagerImpl.addUser()方法!   

-----------CGLibProxy------------- .:检查权限 checkPopedom()! .: 掉用了UserManagerImpl.addUser()方法! -----------JDKProxy------------- .:检查权限 checkPopedom()! .: 掉用了UserManagerImpl.addUser()方法!

 

 

 

JDK代理是不需要以来第三方的库,只要要JDK环境就可以进行代理,它有几个要求

 

* 实现InvocationHandler

* 使用Proxy.newProxyInstance产生代理对象

* 被代理的对象必须要实现接口

 

CGLib 必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承

 

但是针对接口编程的环境下推荐使用JDK的代理

在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行

 

所以在是实际的开发当中,开发人员应该根据实际的需求来选择合适的代理工具。

转载地址:http://utzml.baihongyu.com/

你可能感兴趣的文章
匈奴的历史简述
查看>>
【自然框架之SSO】实现SSO的一个初步想法
查看>>
Can't create/write to file '/tmp/MLjnvU95' (Errcode: 13 - Permission denied)
查看>>
[iphone-cocos2d]关于Loading的若干处理和讨论
查看>>
EJB---->JMS(Java Message Service)和消息驱动bean
查看>>
HDU 1035 Robot Motion(简单题,模拟)
查看>>
Linux 数据流重定向
查看>>
I.MX6 android 4.2 源码下载
查看>>
md5sum 生成 经md5加密后的字符串
查看>>
PowerShell应用之-批量执行SQL脚本
查看>>
职场加薪步步高升的五大法则
查看>>
增删主键及修改表名
查看>>
Gson库使用-排序字段(ExclusionStrategy)或者修改(FieldNamingStrategy)字段
查看>>
[医疗]DICOM VR数据类型表
查看>>
把原来可空的列变成主键
查看>>
shell 中的不相等怎么表达?大于、小于又怎么表达?
查看>>
WIF基本原理(4)联合身份验证实例
查看>>
HDFS写入和读取流程
查看>>
ScrollView 简单出错
查看>>
[置顶] VC++界面编程之--自定义CEdit(编辑框)皮肤
查看>>