转载自:CGLib动态代理的介绍及用法(单回调、多回调、不处理、固定值、懒加载)
本文将介绍下CGLib动态代理及几种用法。CGLib(Code Generation Library)是一个高效的代码生成库,底层实现是使用asm来转换字节码生成类。在生成代理类的场景中,由于JDK动态代理必须要求源对象有实现接口,而实际场景中,并不是所有类都有实现接口,因此使用CGLib可以用在未实现接口的类上。
值得注意的几点是:
-
使用CGLib代理的类不能是final修饰的,因为代理类需要继承主题类;
-
final修饰的方法不会被切入;
-
如果主题类的构造函数不是默认空参数的,那么在使用Enhancer类create的时候,选择create(java.lang.Class[] argumentTypes, java.lang.Object[] arguments) 方法。
接下来认识实现动态代理最重要的一个接口 MethodInteceptor
package net.sf.cglib.proxy;
/**
* General-purpose {@link Enhancer} callback which provides for "around advice".
* @author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">baliuka@mwm.lt</a>
* @version $Id: MethodInterceptor.java,v 1.8 2004/06/24 21:15:20 herbyderby Exp $
*/
public interface MethodInterceptor
extends Callback
{
/**
* All generated proxied methods call this method instead of the original method.
* The original method may either be invoked by normal reflection using the Method object,
* or by using the MethodProxy (faster).
* @param obj "this", the enhanced object
* @param method intercepted Method
* @param args argument array; primitive types are wrapped
* @param proxy used to invoke super (non-intercepted method); may be called
* as many times as needed
* @throws Throwable any exception may be thrown; if so, super method will not be invoked
* @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.
* @see MethodProxy
*/
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
MethodProxy proxy) throws Throwable;
}
MethodInterceptor,从名字上方法拦截器,就是对方法做切入的。intercept方式的4个参数分别对应增强对象、调用方法、方法参数以及调用父类方法的代理。使用MethodProxy速度会更快,所以后面将用
下面介绍几种用法,这里使用spring包中cglib,其实和引单独的cglib包是一样,只不过spring为了版本不冲突,将cglib包含在自己的包中。
先定义一个主题对象
public class DBQuery {
public DBQuery() {
}
public DBQuery(Integer i) {
System.out.println("Here's in DBQuery Constructor");
}
public String getElement(String id) {
return id + "_CGLib";
}
public List<String> getAllElements() {
return Arrays.asList("Hello_CGLib1", "Hello_CGLib2");
}
public String methodForNoop() {
return "Hello_Noop";
}
public String methodForFixedValue(String param) {
return "Hello_" + param;
}
public final String sayHello() {
return "Hello Everyone!";
}
(一)单回调
切入类:
public class DBQueryProxy implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("Here in interceptor !");
return methodProxy.invokeSuper(o, objects);
}
}
测试类:
public class TestCGLibProxy {
public static void main(String[] args) {
DBQueryProxy dbQueryProxy = new DBQueryProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(DBQuery.class);
enhancer.setCallback(dbQueryProxy);
// DBQuery dbQuery = (DBQuery)enhancer.create(new Class[]{Integer.class}, new Object[]{1});
DBQuery dbQuery = (DBQuery) enhancer.create();
System.out.println(dbQuery.getElement("Hello"));
System.out.println();
System.out.println(dbQuery.getAllElements());
System.out.println();
System.out.println(dbQuery.sayHello());
}
}