十三、spring aop之查找匹配的增強(qiáng)器

接上一節(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ù)模式之外,所有部分都是可選的,通配符*表示所有的。
下面有一些示例:

  1. 匹配所有public修飾的方法
execution(public * *(..))
  1. 匹配所有set開頭的方法
execution(* set*(..))
  1. 匹配AccountService接口所有的方法
execution(* com.xyz.service.AccountService.*(..))
  1. 匹配service包下所有的方法
execution(* com.xyz.service.*.*(..))
  1. 匹配service包以及子包所有方法
execution(* com.xyz.service..*.*(..))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容