首页 > 开发 > Java > 正文

Spring中的两种代理JDK和CGLIB的区别浅谈

2024-07-13 10:06:04
字体:
来源:转载
供稿:网友

一、原理区别:

Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

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

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

如何强制使用CGLIB实现AOP?

(1)添加CGLIB库,SPRING_HOME/cglib/.jar

(2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK动态代理和CGLIB字节码生成的区别?

(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类

 (2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法

因为是继承,所以该类或方法最好不要声明成final

二、代码实现

package com.fy.spring.proxy;    public interface UserManager {    public void addUser(String id, String password);    public void delUser(String id);  }  
package com.fy.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动态代理类

package com.fy.spring.proxy;  import java.lang.reflect.InvocationHandler;  import java.lang.reflect.Method;  import java.lang.reflect.Proxy;  /**   *   * JDK动态代理类   *   *   */ 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动态代理类

package com.fy.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动态代理类的实例   *    *   */ 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()!");    }  }  

测试类:

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

运行结果:

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

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

  1.  实现InvocationHandler
  2.  使用Proxy.newProxyInstance产生代理对象
  3.  被代理的对象必须要实现接口

CGLib 必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用JDK的代理

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

希望本文所述对你有所帮助,Spring中的两种代理JDK和CGLIB的区别浅谈内容就给大家介绍到这里了。希望大家继续关注我们的网站!想要学习java可以继续关注本站。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表