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

Java CGLib动态代理机制(全面解析)

程序员文章站 2024-02-18 11:42:34
一、首先说一下jdk中的动态代理: jdk中的动态代理是通过反射类proxy以及invocationhandler回调接口实现的 但是,jdk中所要进行动态代理的类必须...

一、首先说一下jdk中的动态代理:

jdk中的动态代理是通过反射类proxy以及invocationhandler回调接口实现的

但是,jdk中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。

二、使用cglib实现:

使用cglib实现动态代理,完全不受代理类必须实现接口的限制,而且cglib底层采用asm字节码生成框架,使用字节码技术生成代理类,比使用java反射效率要高。唯一需要注意的是,cglib不能对声明为final的方法进行代理,因为cglib原理是动态生成被代理类的子类。

下面,将通过一个实例介绍使用cglib实现动态代理。

1、被代理类:

首先,定义一个类,该类没有实现任何接口,包含两个方法。

public class concreteclassnointerface { 
 public string getconcretemethoda(string str){ 
  system.out.println("concretemethod a ... "+str); 
  return str; 
 } 
 public int getconcretemethodb(int n){ 
  system.out.println("concretemethod b ... "+n); 
  return n+10; 
 } 
}

2、拦截器:

定义一个拦截器。在调用目标方法时,cglib会回调methodinterceptor接口方法拦截,来实现你自己的代理逻辑,类似于jdk中的invocationhandler接口。

public class concreteclassinterceptor implements methodinterceptor{ 
 public object intercept(object obj, method method, object[] arg, methodproxy proxy) throws throwable { 
  system.out.println("before:"+method); 
  object object=proxy.invokesuper(obj, arg); 
  system.out.println("after:"+method); 
  return object; 
 } 
} 

参数:object为由cglib动态生成的代理类实例,method为上文中实体类所调用的被代理的方法引用,object[]为参数值列表,methodproxy为生成的代理类对方法的代理引用。

返回:从代理实例的方法调用返回的值。

其中,proxy.invokesuper(obj,arg):

调用代理类实例上的proxy方法的父类方法(即实体类concreteclassnointerface中对应的方法)

在这个示例中,只在调用被代理类方法前后各打印了一句话,当然实际编程中可以是其它复杂逻辑。

3、生成动态代理类:

enhancer enhancer=new enhancer(); 
enhancer.setsuperclass(concreteclassnointerface.class); 
enhancer.setcallback(new concreteclassinterceptor()); 
concreteclassnointerface ccni=(concreteclassnointerface)enhancer.create(); 

这里enhancer类是cglib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展,以后会经常看到它。

首先将被代理类concreteclassnointerface设置成父类,然后设置拦截器concreteclassinterceptor,最后执行enhancer.create()动态生成一个代理类,并从object强制转型成父类型concreteclassnointerface。

最后,在代理类上调用方法:

ccni.getconcretemethoda("shensy"); 
ccni.getconcretemethodb(0); 

查看控制台输出:

before :public java.lang.string generic.cglib.proxy.concreteclassnointerface.getconcretemethoda(java.lang.string) 
concretemethod a ... shensy 
after :public java.lang.string generic.cglib.proxy.concreteclassnointerface.getconcretemethoda(java.lang.string) 
before :public int generic.cglib.proxy.concreteclassnointerface.getconcretemethodb(int) 
concretemethod b ... 0 
after :public int generic.cglib.proxy.concreteclassnointerface.getconcretemethodb(int) 

可以看到,拦截器在调用被代理类方法前后都执行了print操作。

以上这篇java cglib动态代理机制(全面解析)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。