盘点 AOP AOP 的拦截对象的创建

首先分享之前的所有文章 , 欢迎点赞收藏转发三连下次一定 >>>> 😜😜😜

文章合集 : 🎁 juejin.cn/post/694164…

Github : 👉 github.com/black-ant

一 . 前言

之前说了 AOP初始化AOP 代理类的创建 , 这一篇来看一下 AOP 拦截对象的创建

二 . CglibAopProxy 代理模块

AOP 的主要代理类还是 CglibAopProxy , 所以整体流程还是以该对象为例 :

2.1 拦截对象创建的入口

在 CglibAopProxy # getProxy 主流程中 , 有几个比较重要的逻辑 , 把这几个流程整合后看一下 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
java复制代码// 代码做过一定程度的省略和魔改
public Object getProxy(@Nullable ClassLoader classLoader) {

//... 省略主要逻辑
Enhancer enhancer = createEnhancer();

// rootClass => com.gang.aop.demo.service.StartService
// 获取所有的回调对象 -> PIC21001 : Callback[] 系列参数
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}

enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap,
this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);

// Generate the proxy class and create a proxy instance.
// return createProxyClassAndInstance(enhancer, callbacks);
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}

PIC21001 : Callback[] 系列参数

image.png

2.1.1 创建 Callback 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
java复制代码private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// 是否为每次调用公开AOP代理
boolean exposeProxy = this.advised.isExposeProxy();
// 配置是否被冻结,并且不能进行通知更改
boolean isFrozen = this.advised.isFrozen();
// 是否所有对#getTarget()的调用都返回同一个对象
boolean isStatic = this.advised.getTargetSource().isStatic();

// 选择一个 AOP 拦截器 -> 此处创建的是 DynamicAdvisedInterceptor , 这是一个重要的类 -> 2.1.2
// advised -> PIC21101
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

// 选择性创建 StaticUnadvisedInterceptor / DynamicUnadvisedInterceptor
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}

// 选择一个目标分派器
// StaticDispatcher : 静态目标的调度器 , Dispatcher比Interceptor快得多
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

// PICPIC21102
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};

Callback[] callbacks;

// 如果目标是静态的,并且通知链是冻结的,那么我们可以通过使用该方法的固定链将AOP调用直接发送到目标
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);

for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}

// 从mainCallbacks和fixedCallbacks复制回调函数到callbacks数组中
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
// 返回所有的回调对象
return callbacks;
}

PIC21101 advised 中已经包含目标对象和通知面

image.png

PIC21102 : mainCallbacks 结构

image.png

扩展 : ProxyCallbackFilter 的作用

作用: CallbackFilter为方法分配回调

介绍: 该类实现了一个 Accept 方法 , 用于返回回调函数的索引

1
2
3
4
5
6
7
8
9
java复制代码private static class ProxyCallbackFilter implements CallbackFilter {

private final AdvisedSupport advised;

private final Map<Method, Integer> fixedInterceptorMap;

private final int fixedInterceptorOffset;

}

2.1.2 DynamicAdvisedInterceptor

作用 : 当目标是动态的或代理未被冻结时使用 , 会使用该通用的AOP回调

发起 : 从 2.1.1 中 getCallbacks 中可以看到创建流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
java复制代码// 那么来看一下这个对象是如何实现方法的拦截的
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

// PRO212001 : AdvisedSupport 的作用
private final AdvisedSupport advised;

public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}

@Override
@Nullable
// proxy -> EnhancerBySpringCGLIB 代理
// method -> 实际业务方法
// args : 方法参数
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
// 当前调用的目标 ,
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 根据此配置确定给定方法的MethodInterceptor对象列表
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 检查我们是否只有一个InvokerInterceptor (没有通知 , 只有反射调用)
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 方法代理直接调用
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 核心逻辑 , 此处创建了一个方法调用
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 处理返回类型
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// 恢复旧的代理
AopContext.setCurrentProxy(oldProxy);
}
}
}
}



// SingletonTargetSource 对象结构
public class SingletonTargetSource implements TargetSource, Serializable {

// 使用反射缓存和调用的目标
private final Object target;
}

// CglibMethodInvocation 结构
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

@Nullable
private final MethodProxy methodProxy;

public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
Object[] arguments, @Nullable Class<?> targetClass,
List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);

// 仅对非java.lang.Object派生的公共方法使用方法代理
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
methodProxy : null);
}

可以看到 , DynamicAdvisedInterceptor 是 MethodInterceptor 的实现类 , 该接口对方法进行拦截

MethodInterceptor 的继承体系 :
Systerm-DynamicAdvisedInterceptor.png

PRO212001 : AdvisedSupport 的作用

作用 : AOP代理配置管理器的基类。其本身不是AOP代理,但是该类的子类通常是工厂,从这些工厂中直接获得AOP代理实例

特点 : 这个类是可序列化的 , 用于保存代理的快

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
java复制代码
public class AdvisedSupport extends ProxyConfig implements Advised {

// 通知链工厂 -> Pro
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

// key 为方法缓存 , value 为 advisor 链
private transient Map<MethodCacheKey, List<Object>> methodCache;

// 代理要实现的接口
private List<Class<?>> interfaces = new ArrayList<>();

// Advisor 对象集合 , 每一个通知会包装为通知者放在该集合中
private List<Advisor> advisors = new ArrayList<>();

// 用于内部操作 , advisor 改变后会刷新该对象
private Advisor[] advisorArray = new Advisor[0];

}

// AdvisorChainFactory 的作用

System-AdvisedSupport.png

代理的核心逻辑 :

对应的方法已经在前面通过 Enhancer 进行 CGLIB 代理了 , 调用时实际调用的是 DynamicAdvisedInterceptor , 再由 DynamicAdvisedInterceptor 完成 AOP 类的调用

PS : 这里涉及到动态代理的相关概念 ,会生成 xxx$$EnhancerBySpringCGLIB$$… 的实际类 , 进行 Class 层面的调用 , 这些后面单独说说

总结

请求方DynamicAdvisedInterceptorCglibMethodInvocation切面请求方调用 Interceptor 对象调用 CglibMethodInvocation 发起切面的调用实际调用到切面对象 , 执行对应的通知方法请求方DynamicAdvisedInterceptorCglibMethodInvocation切面
后续就是 ReflectiveMethodInvocation 调用具体的方法 ,这里先不说

还是感觉没说清楚 , 整个条理不是很清楚 , 考虑整个系列完成后进行一次深入打磨 , 欢迎关注 👉

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%