当前位置: 移动技术网 > IT编程>开发语言>Java > Spring中的两种代理JDK和CGLIB的区别浅谈

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

2019年07月22日  | 移动技术网IT编程  | 我要评论
一、原理区别: 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可以继续关注本站。

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网