【探索Spring底层】MethodProxy原理
1. 前言回顾
在前面了解了jdk代理与cglib代理原理
详细可以查看这里【探索Spring底层】8.手撕jdk代理原理与cglib代理原理
在学习cglib代理原理的时候,了解到执行需要增强的方法时候有两种方法
- 反射调用
- 代理调用
而MethodProxy内部有两种不需要用反射的调用方法
- invoke:内部无反射,结合目标使用
- invokeSuper:内部无反射,结合代理使用
下面就详述一下这两个方法的底层实现
2. 手撕invoke
当调用了methodProxy.invoke方法后,会动态生成TargetFastClass类
这个类里面有两个主要的方法
- getIndex:获取目标的编号;TargetFastClass记录了目标方法与编号的对应关系,比如说save方法对应的编号是0。只需要传递签名信息即可返回方法对应的编号
- invoke:根据方法编号,正常调用目标方法,三个参数分别代表
- index:方法编号
- target:目标对象
- args:方法执行所需参数
ps:
Signature签名对象包含了方法名字、参数返回值
这些签名信息在MethodProxy创建的时候就会生成
save0Proxy = MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper"); save1Proxy = MethodProxy.create(Target.class, Proxy.class, "(I)V", "save", "saveSuper"); save2Proxy = MethodProxy.create(Target.class, Proxy.class, "(J)V", "save", "saveSuper");
public class TargetFastClass {
static Signature s0 = new Signature("save", "()V");
static Signature s1 = new Signature("save", "(I)V");
static Signature s2 = new Signature("save", "(J)V");
// 获取目标方法的编号
/*w
Target
save() 0
save(int) 1
save(long) 2
signature 包括方法名字、参数返回值
*/
public int getIndex(Signature signature) {
if (s0.equals(signature)) {
return 0;
} else if (s1.equals(signature)) {
return 1;
} else if (s2.equals(signature)) {
return 2;
}
return -1;
}
// 根据方法编号, 正常调用目标对象方法
public Object invoke(int index, Object target, Object[] args) {
if (index == 0) {
((Target) target).save();
return null;
} else if (index == 1) {
((Target) target).save((int) args[0]);
return null;
} else if (index == 2) {
((Target) target).save((long) args[0]);
return null;
} else {
throw new RuntimeException("无此方法");
}
}
}
测试类
- 首先获取方法对象的编号
- 然后使用TargetFastClass的invoke方法正常调用
public static void main(String[] args) {
TargetFastClass fastClass = new TargetFastClass();
int index = fastClass.getIndex(new Signature("save", "(I)V"));
System.out.println(index);
fastClass.invoke(index, new Target(), new Object[]{100});
}
3. 手撕invokeSuper
当调用了methodProxy.invokeSuper方法后,会动态生成ProxyFastClass类
在了解了上面invoke的底层实现后,想要理解invokeSuper就会变得非常简单
invokeSuper的不同只是签名的不一样罢了
在TargetFastClass内部的签名对象是带增强功能的方法
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 带增强功能的方法
@Override
public void save() {
try {
methodInterceptor.intercept(this, save0, new Object[0], save0Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(int i) {
try {
methodInterceptor.intercept(this, save1, new Object[]{i}, save1Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(long j) {
try {
methodInterceptor.intercept(this, save2, new Object[]{j}, save2Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
而ProxyFastClass内部的签名信息则是带原始功能的方法,其他均一致
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 带原始功能的方法
public void saveSuper() {
super.save();
}
public void saveSuper(int i) {
super.save(i);
}
public void saveSuper(long j) {
super.save(j);
}
public class Proxy extends Target {
private MethodInterceptor methodInterceptor;
public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
static Method save0;
static Method save1;
static Method save2;
static MethodProxy save0Proxy;
static MethodProxy save1Proxy;
static MethodProxy save2Proxy;
static {
try {
save0 = Target.class.getMethod("save");
save1 = Target.class.getMethod("save", int.class);
save2 = Target.class.getMethod("save", long.class);
/**
* 目标类型
* 代理类型
* 带增强功能的方法名
* 带原始功能的方法
*/
save0Proxy = MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
save1Proxy = MethodProxy.create(Target.class, Proxy.class, "(I)V", "save", "saveSuper");
save2Proxy = MethodProxy.create(Target.class, Proxy.class, "(J)V", "save", "saveSuper");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 带原始功能的方法
public void saveSuper() {
super.save();
}
public void saveSuper(int i) {
super.save(i);
}
public void saveSuper(long j) {
super.save(j);
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 带增强功能的方法
@Override
public void save() {
try {
methodInterceptor.intercept(this, save0, new Object[0], save0Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(int i) {
try {
methodInterceptor.intercept(this, save1, new Object[]{i}, save1Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(long j) {
try {
methodInterceptor.intercept(this, save2, new Object[]{j}, save2Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
//测试方法
public static void main(String[] args) {
ProxyFastClass fastClass = new ProxyFastClass();
int index = fastClass.getIndex(new Signature("saveSuper", "()V"));
System.out.println(index);
fastClass.invoke(index, new Proxy(), new Object[0]);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/94987.html