spring 12 cglib 代理进阶
cglib 代理进阶
模拟 cglib 代理
示例
public static void main(String[] args) {
S12Target target = new S12Target();
S12Proxy s12Proxy = new S12Proxy(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("前置增强");
// method.invoke(target, args);// 反射调用
methodProxy.invoke(target, args); // 非反射调用,需要目标对象 Spring 使用
// methodProxy.invokeSuper(proxy, args); // 非反射调用,需要代理对象
System.out.println("后置增强");
return null;
}
});
s12Proxy.s120();
s12Proxy.s121(1);
s12Proxy.s122(2,3);
}
// 模拟代理类
public class S12Proxy extends S12Target {
// cjlib 提供的接口
private MethodInterceptor methodInterceptor;
public S12Proxy(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
static Method m1;
static Method m2;
static Method m3;
static MethodProxy mp1;
static MethodProxy mp2;
static MethodProxy mp3;
static {
try {
m1 = S12Target.class.getMethod("s120");
m2 = S12Target.class.getMethod("s121", int.class);
m3 = S12Target.class.getMethod("s122", int.class, int.class);
mp1 = MethodProxy.create(S12Target.class, S12Proxy.class, "()V", "s120", "ss120");
mp2 = MethodProxy.create(S12Target.class, S12Proxy.class, "(I)V", "s121", "ss121");
mp3 = MethodProxy.create(S12Target.class, S12Proxy.class, "(II)V", "s122", "ss122");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
public void ss120() {
super.s120();
}
public void ss121(int i) {
super.s121(i);
}
public void ss122(int i, int j) {
super.s122(i, j);
}
@Override
public void s120() {
try {
methodInterceptor.intercept(this, m1, new Object[0], mp1);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void s121(int i) {
try {
methodInterceptor.intercept(this, m2, new Object[]{i}, mp2);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void s122(int i, int j) {
try {
methodInterceptor.intercept(this, m3, new Object[]{i,j}, mp3);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
// 目标类
public class S12Target {
public void s120() {
System.out.println("s120 running...");
}
public void s121(int i) {
System.out.println("s121 running...");
}
public void s122(int i,int j) {
System.out.println("s122 running...");
}
}
和 jdk 动态代理原理查不多
- 回调的接口换了一下,InvocationHandler 改成了 MethodInterceptor
- 调用目标时有所改进,见下面代码片段
- method.invoke 是反射调用,必须调用到足够次数才会进行优化
- methodProxy.invoke 是不反射调用,它会正常(间接)调用目标对象的方法(Spring 采用)
- methodProxy.invokeSuper 也是不反射调用,它会正常(间接)调用代理对象的方法,可以省略目标对象
注意
- 调用 Object 的方法, 后两种在 jdk >= 9 时都有问题, 需要 --add-opens java.base/java.lang=ALL-UNNAMED

浙公网安备 33010602011771号