引言

这篇文章主要分析对于指定的类,获取它的合适的增强器,看入口方法:

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
/**
* 确定适用于给定类的candidateAdvisors列表的子列表。
* @param candidateAdvisors 候选Advisors
* @param clazz the target class
* @return 可以应用于给定类的对象的Advisors的子列表
* (may be the incoming List as-is)
*/
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
//迭代候选Advisors
for (Advisor candidate : candidateAdvisors) {
//获取IntroductionAdvisor类型的Advisor
//处理IntroductionAdvisor类型的Advisor和普通的Advisor不一样,所以先单独处理
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//获取普通类型的Advisors
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}

首先处理IntroductionAdvisor类型的增强器,再处理普通类型,但是最终都是调用canApply(candidate, clazz, hasIntroductions);

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
/**
* Can the given advisor apply at all on the given class?
* This is an important test as it can be used to optimize
* out a advisor for a class.
* @param advisor the advisor to check
* @param targetClass class we're testing
* @return whether the pointcut can apply on any method
*/
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
/**
* 给定的advisor是否可以应用于给定的类?
* 这是一个重要的测试,因为它可以用来优化类的advisor。
* 这个版本还考虑了introductions(对于IntroductionAwareMethodMatchers)。
* @param advisor advisor检查
* @param targetClass 目标类
* @param hasIntroductions 这个bean的advisor链是否包含任何introductions
* @return 切入点是否可以应用于任何方法
*/
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
//处理IntroductionAdvisor类型的Advisor
if (advisor instanceof IntroductionAdvisor) {
//获取ClassFilter,调用matches方法
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
//处理PointcutAdvisor类型的Advisor
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// 它没有切入点,所以我们假设它适用。
return true;
}
}

在处理PointcutAdvisor的时候,调用Pointcut类型的canApply:

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
/**
* 给定的切入点是否可以应用于给定的类?
* 这是一个重要的测试,因为它可以用来优化类的切入点。
* @param pc 要检查的静态或动态切入点
* @param targetClass the class to test
* @param hasIntroductions 这个bean的advisor链是否包含introductions
* @return 切入点是否可以应用于任何方法
*/
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//使用 ClassFilter 匹配 class
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}

MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// 如果我们匹配任何方法,都不需要迭代方法……
return true;
}

IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}

//查找当前类及其父类(以及父类的父类等等)所实现的接口,由于接口中的方法是 public,
//所以当前类可以继承其父类,和父类的父类中所有的接口方法
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

for (Class<?> clazz : classes) {
// 获取当前类的方法列表,包括从父类中继承的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 使用 methodMatcher 匹配方法,匹配成功即可立即返回
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}

return false;
}

筛选的工作主要由 ClassFilter 和 MethodMatcher 完成,比如AspectJExpressionPointcut的实现了ClassFilter和MethodMatcher接口,最终由AspectJ表达式解析,这个地方就复杂了,先不看了。

tencent.jpg