欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-01 20:47:10
一、原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用invokehandler来处理。 而cglib动态代理是利用a...

一、原理区别:

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可以继续关注本站。