在 CGLib 中,MethodInterceptor 接口是 Enhancer 回调类型,它用来拦截某个方法,在调用方法前后完成其他操作。熟悉 Spring AOP 面向切面编程的读者应该知道,在 Spring AOP 中支持环绕通知,即在调用方法的前后完成其他操作。其实,Spring AOP 的环绕通知和 CGLib MethodInterceptor 类似。该回调接口仅仅定义了一个 intercept() 方法,定义如下:
java.lang.Object intercept(java.lang.Object obj, java.lang.reflect.Method method, java.lang.Object[] args, MethodProxy proxy) throws java.lang.Throwable
所有生成的代理方法都调用此方法而不是原始方法。原始方法可以通过使用 Method 对象的正常反射调用,也可以使用 MethodProxy(更快)调用。
参数说明:
obj:表示“this”,被增强的对象;
method:被调用的方法的 Method 对象;
args:参数数组,如果是原始类型,则使用包装类型;
proxy:用于调用 super (非截取方法),可以根据需要多次调用;
返回:
返回一个与代理方法签名兼容的任何值。如果代理方法返回值为 void,则此方法将忽略此值。
(1)定义被代理对象,代码如下:
/**
* 被代理的类
* @author hxstrive.com 2021/12/29
*/
public class HelloWorld {
public void test(String msg) {
System.out.println(msg);
}
}(2)客户端代码,通过 intercept() 方法的 MethodProxy 对象调用目标方法(即 HelloWorld 的 test() 方法)。代码如下:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 验证 setCallback() 设置 MethodInterceptor 接口
* @author hxstrive.com 2021/12/31
*/
public class CglibDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloWorld.class);
// 你可以认为定义了 MethodInterceptor 拦截器
// 它拦截所有方法,我们就可以在方法执行前后进行处理
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("call method before");
// 调通 CGLib 的方法代理对象调用目标方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("call method after");
return result;
}
});
HelloWorld sample = (HelloWorld) enhancer.create();
sample.test("hello world");
}
}运行上面程序,输出如下:
call method before hello world call method after
根据上面输出结果,我们可以在执行目标方法前后进行其他任何操作。