Spring AOP 依靠 JDK 和 CGLib 进行动态代理实现。在此对两种实现方式的一些知识进行整理。
JDK
使用示例
/**
* 需要被代理的接口
*/
interface Iinterface {
String proxyMethod(String gift);
}
/**
* 实现 InvocationHandler 接口,对 invoke 方法进行重写
*/
class MyHandler implements {
/**
* @param proxy 生成的代理实例
* @param method 被代理类的方法
* @param args 传入的参数列表
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 对应被代理的方法
if (method.getName().equals("proxyMethod")) {
System.out.println("接受到参数:" + args[0]);
return "返回值";
}
return null;
}
}
public class Main {
public static void main(String[] args) {
Iinterface proxy = (Iinterface) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{Iinterface.class},
new MyHandler()
);
String res = proxy.proxyMethod("传入的参数");
System.out.println(res);
}
}
可见代理成功。
概括一下,动态代理的方式一般为:
-
继承
InvocationHandler
,重写方法invoke
-
执行
Proxy.newProxyInstance
生成动态代理类
invoke 方法
由上可以看出,proxy 成功对 Iinterface 接口进行代理,但是在使用时,我们并未见到 InvocationHandler 中 invoke
方法的调用,动态代理是如何执行 invoke
的呢?
采用其他资料生成的案例,以下是代理类的反编译代码。
首先来看看代理类的继承关系:
可以看到代理类继承了 Proxy ,再来看看代理类中的方法调用,其中 teach()
是被代理接口的方法声明,内部知识简单地调用了父类即 Proxy 的 h 属性的 invoke
方法
再回看 Proxy 类的属性
可以猜测,对被代理方法进行调用时,会转而由被代理类中继承自 Proxy 的 InvocationHandler 执行,从而 invoke
方法被调用。再来看看调用的 newProxyInstance
的逻辑,代码进行了省略,添加了简单注释
public static