zoukankan      html  css  js  c++  java
  • Spring 中JDKProxy和CGlibProxy的区别

    环境要求

     

    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接口

    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. }  

    接下来是其实现类  UserManagerImpl

    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. }  

    JDK动态代理类

    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. }  

    CGLibProxy动态代理类

    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. }  

    下面来测试下

    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. }  

    执行结果是:

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

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

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

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

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

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

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

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

    Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear. 面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!
  • 相关阅读:
    UICollectionView
    UIDynamicPPT
    05-UIDynamic
    键盘处理return key-工具条
    源代码管理工具 git
    源代码管理工具
    核心动画09-CATransition转场动画
    核心动画06-时钟(了解)
    Intersect,Minus,union all 和union的区别
    freemarker大于,小于 gt,lt 的用法
  • 原文地址:https://www.cnblogs.com/200911/p/2627145.html
Copyright © 2011-2022 走看看