在 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
根据上面输出结果,我们可以在执行目标方法前后进行其他任何操作。