接上一節(jié)十二、spring aop之查找所有增強(qiáng)器, 上一節(jié)我們分析了spring是如何查找所有的Advisor(增強(qiáng)器),這節(jié)我們分析匹配當(dāng)前bean的Advisor(增強(qiáng)器),只有有匹配的才需要?jiǎng)?chuàng)建代理。實(shí)現(xiàn)邏輯還是在AbstractAdvisorAutoProxyCreator#findEligibleAdvisors(Class<?> beanClass, String beanName)中。
findEligibleAdvisors方法的實(shí)現(xiàn)代碼如下:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//1. 查找所有的增強(qiáng)器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//2. 找到匹配當(dāng)前bean的增強(qiáng)器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
不過這節(jié)我們分析的是findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)方法。
findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//過濾已經(jīng)得到的Advisors
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
AopUtils.findAdvisorsThatCanApply()實(shí)現(xiàn)邏輯:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
for (Advisor candidate : candidateAdvisors) {
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;
}
//調(diào)試代碼執(zhí)行這一行,IntroductionAdvisor增強(qiáng)器我也不知道在什么時(shí)候使用
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
findAdvisorsThatCanApply方法的主要功能是尋找所有Advisor(增強(qiáng)器)中適用于當(dāng)前class的Advisor,而對(duì)于真正的匹配在canApply方法中實(shí)現(xiàn)。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
//spring aop生成的增強(qiáng)器是InstantiationModelAwarePointcutAdvisorImpl對(duì)象,實(shí)現(xiàn)了PointcutAdvisor
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//匹配類
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//匹配方法
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
//遍歷所有方法,找到匹配的方法就返回
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
匹配規(guī)則是,先匹配類,再遍歷方法是否有匹配的。canApply方法是一個(gè)短路操作,只要找到一個(gè)匹配就返回true,說明bean是需要被代理的。這里我不分析spring是如何執(zhí)行匹配的,閱讀源碼得有個(gè)度,我們只需要知道spring給我們規(guī)定的規(guī)則就好,我們切點(diǎn)匹配使用最多的是execution。接下來分析execution規(guī)則。
execution規(guī)則
execution格式如下
//execution(<修飾符模式>?<返回類型模式><方法名模式>(<參數(shù)模式>)<異常模式>?)
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
除了返回類型模式(上面代碼片段中的ret-type模式)、方法名模式和參數(shù)模式之外,所有部分都是可選的,通配符*表示所有的。
下面有一些示例:
- 匹配所有public修飾的方法
execution(public * *(..))
- 匹配所有set開頭的方法
execution(* set*(..))
- 匹配AccountService接口所有的方法
execution(* com.xyz.service.AccountService.*(..))
- 匹配service包下所有的方法
execution(* com.xyz.service.*.*(..))
- 匹配service包以及子包所有方法
execution(* com.xyz.service..*.*(..))