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. 面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!
  • 相关阅读:
    使用golang访问kubebernetes
    使用 Rancher 管理现有 Kubernetes 集群
    Running powershell scripts during nuget package installation and removal
    How to Create, Use, and Debug .NET application Crash Dumps in 2019
    寻找写代码感觉(一)之使用 Spring Boot 快速搭建项目
    Selenium+Java之解决org.openqa.selenium.InvalidArgumentException: invalid argument报错问题
    Selenium环境搭建
    关于Xpath定位方法知道这些基本够用
    Web自动化之浏览器启动
    【翻译】编写代码注释的最佳实践
  • 原文地址:https://www.cnblogs.com/200911/p/2627145.html
Copyright © 2011-2022 走看看