Plugin 实现了 InvocationHandler 接口,因此它的 invoke 方法会拦截所有的方法调用。

invoke 方法会对所拦截的方法进行检测,以决定是否执行插件逻辑。该方法的逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// -☆- Plugin
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {
// 获取被拦截方法列表,比如:signatureMap.get(Executor.class),
// 可能返回 [query, update, commit]
Set<Method> methods = signatureMap.get(method.getDeclaringClass());
// 检测方法列表是否包含被拦截的方法
if (methods != null && methods.contains(method)) {
// 执行插件逻辑
return interceptor.intercept(
new Invocation(target, method, args));
}
// 执行被拦截的方法
return method.invoke(target, args);
} catch (Exception e) {
throw ExceptionUtil.unwrapThrowable(e);
}
}

首先,invoke 方法会检测被拦截方法是否配置在插件的@Signature注解中,若是,则执行插件逻辑,否则执行被拦截方法。插件逻辑封装在 intercept 中,该方法的参数类型为 Invocation。

Invocation 主要用于存储目标类,方法以及方法参数列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Invocation {
private final Object target;
private final Method method;
private final Object[] args;
public Invocation(Object target, Method method, Object[] args) {
this.target = target;
this.method = method;
this.args = args;
}
public Object proceed()
throws InvocationTargetException, IllegalAccessException {
// 调用被拦截的方法
return method.invoke(target, args);
}
}