1. 程式人生 > 實用技巧 >Spring AOP 自動代理建立器

Spring AOP 自動代理建立器

除錯環境:https://gitee.com/jhxxb/MySpringBoot/tree/master/spring-base/Spring-AOP

原始碼

從@EnableAspectJAutoProxy 註解開始

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) // 給容器中匯入了 AspectJAutoProxyRegistrar
public @interface EnableAspectJAutoProxy {
    
/** * 用 CGLIB 代理還是用 JDK 動態代理(需要實現介面),預設為 false,用 JDK 動態代理 */ boolean proxyTargetClass() default false; /** * 代理的暴露方式:解決內部呼叫不能使用代理的場景,預設為 false 表示不處理 * true:這個代理就可以通過 AopContext.currentProxy() 獲得這個代理物件的一個副本(ThreadLocal 裡面),從而我們可以很方便得在 Spring 框架上下文中拿到當前代理物件(處理事務時很方便) * 必須為 true 才能呼叫 AopContext 的方法,否則報錯:Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available. *
@since 4.3.1 */ boolean exposeProxy() default false; }

AspectJAutoProxyRegistrar

這一步注入了一個 Bean:AnnotationAwareAspectJAutoProxyCreator,基於註解的自動代理建立器,應儘量避免自己建立 AutoProxyCreator,而是統一交給 Spring 來處理

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 這步非常重要,就是去註冊了一個基於註解的 AspectJ 自動代理建立器(如果需要的話) AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy != null) { // 若為 true,表示強制指定了要使用 CGLIB,那就強制告知到時候使用 CGLIB 的動態代理方式 if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } // 告知,強制暴露 Bean 的代理物件到 AopContext if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } } public abstract class AopConfigUtils { public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator"; // findPriorityForClass 這個方法非常有意思:相當於找到 index 角標,然後 // APC_PRIORITY_LIST 的內容是下面這幾個,按照順序排好的 private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3); static { APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); } @Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null); } @Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } @Nullable private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); // 很顯然,這裡如果我們自己定義了這樣一個自動代理建立器,也是可以的 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); // 如果我們自定義的並不是 cls 這個 class 型別的 Bean,那就做如下處理一下 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { // InfrastructureAdvisorAutoProxyCreator/AspectJAwareAdvisorAutoProxyCreator/AnnotationAwareAspectJAutoProxyCreator 的一個邏輯(防止使用者註冊錯了,做一個容錯處理) int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); // currentPriority < requiredPriority,如果當前使用者註冊進來的 Aop 代理類的級別,是低於我們要求的級別的,Spring 內部也會對它進行提升成我們要求的那個 class 型別 // 這樣符合我們的建議:最好不要自己去使用低級別的自動代理建立器 if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } // 若使用者自己沒有定義,那就用系統定義好的:AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); // 此處注意,增加了一個屬性:最高優先順序執行 beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); // 角色為 Spring 自己使用 beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); // 註冊此 Bean 定義資訊 registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }

AnnotationAwareAspectJAutoProxyCreator:自動代理建立器,AOP 的核心

先看ProxyProcessorSupport

// 繼承 ProxyConfig,擁有 AOP 的基本配置
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
    // 把該 Bean 所有實現的介面,過濾後都作用在 ProxyFactory 上
    protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
        // 拿到該類所有實現的介面
        Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
        // 標記:是否存在“有問題的”代理介面,預設是 false
        boolean hasReasonableProxyInterface = false;
        for (Class<?> ifc : targetInterfaces) {
            // 判斷這些介面是否是“有問題的”:既我們需要處理的
            if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0) {
                hasReasonableProxyInterface = true;
                break;
            }
        }
        // 說明除開哪些介面外,但凡有一個有用的介面,就 add 進去(這樣就會採用 JDK 動態代理了)
        if (hasReasonableProxyInterface) {
            for (Class<?> ifc : targetInterfaces) {
                proxyFactory.addInterface(ifc);
            }
        } else { // 否則直接採用 CGLIB
            proxyFactory.setProxyTargetClass(true);
        }
    }

    // InitializingBean...Aware 介面的子介面等,這些回撥性質的介面
    protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
        return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
                AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
    }

    // 介面名稱為這些的,也就是 spring aop 自己的東西
    protected boolean isInternalLanguageInterface(Class<?> ifc) {
        return (ifc.getName().equals("groovy.lang.GroovyObject") ||
                ifc.getName().endsWith(".cglib.proxy.Factory") ||
                ifc.getName().endsWith(".bytebuddy.MockAccess"));
    }

再看AbstractAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator 是AbstractAutoProxyCreator 的子類,AbstractAutoProxyCreator是對自動代理建立器的一個抽象實現。重要的是,它實現了 SmartInstantiationAwareBeanPostProcessor 介面,因此會介入到 Spring IOC 容器 Bean 例項化的過程,SmartInstantiationAwareBeanPostProcessor 繼承自 InstantiationAwareBeanPostProcessor 繼承自 BeanPostProcessor, 所以它需要實現的方法有很多,重點說一下:在 Bean 被例項化之前,先會執行所有的 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,誰第一個返回了不為 null 的 Bean,後面就都不會執行了 。然後會再執行 BeanPostProcessor#postProcessAfterInitialization 就完事了

主要看postProcessBeforeInstantiation 方法和postProcessAfterInitialization 方法,這兩個是參與 Bean 例項化的

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    /**
     * 在 Bean 例項化之前,給一個機會,看看快取裡有沒有,有就直接返回了
     * 簡單的說:其主要目的在於如果使用者使用了自定義的 TargetSource 物件,則直接使用該物件生成目標物件,而不會使用 Spring 的預設邏輯生成目標物件
     * (並且這裡會判斷各個切面邏輯是否可以應用到當前 bean 上)
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        Object cacheKey = getCacheKey(beanClass, beanName);

        // beanName 無效或者 targetSourcedBeans 裡不包含此 Bean
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            // advisedBeans:已經被通知了的(被代理了的)Bean,如果在這裡面,也返回 null
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            // isInfrastructureClass:Advice、Pointcut、Advisor、AopInfrastructureBean 的子類,表示是框架所屬的 Bean
            // shouldSkip:預設都是返回 false 的。
            // AspectJAwareAdvisorAutoProxyCreator 重寫此方法:只要存在一個 Advisor((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)成立 ,就返回 true
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                // 所以這裡會把我們所有的 Advice、Pointcut、Advisor、AopInfrastructureBean 等 Bean 都裝進來
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }
        // 到這,只有在 TargetSource 中沒有進行快取,並且應該被切面邏輯環繞,但是目前還未生成代理物件的 bean 才會通過此方法

        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean: The TargetSource will handle target instances in a custom fashion.
        // 如果我們有 TargetSourceCreator,這裡就會建立一個代理物件
        // getCustomTargetSource 邏輯:存在 TargetSourceCreator 並且 beanFactory.containsBean(beanName) 然後遍歷所有的 TargetSourceCreator,呼叫 getTargetSource 誰先建立不為 null 就終止
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        // 若建立好了這個代理物件,繼續進一步的操作
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                // 快取起來
                this.targetSourcedBeans.add(beanName);
            }
            // getAdvicesAndAdvisorsForBean:方法判斷當前 Bean 是否需要進行代理,若需要則返回滿足條件的 Advice 或者 Advisor 集合
            // 這個方法由子類實現,AbstractAdvisorAutoProxyCreator 和 BeanNameAutoProxyCreator 代表中兩種不同的代理方式
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            // 根據目標物件建立代理物件的核心邏輯了
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            // 把建立好的代理快取起來
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        return null;
    }

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        // 代理是通過 AbstractAutoProxyCreator 中的 postProcessAfterInitialization() 建立的
        // 因此這個方法是蠻重要的,主要是 wrapIfNecessary() 方法會特別的重要
        // earlyProxyReferences 快取:該快取用於儲存已經建立過代理物件的 cachekey,避免重複建立
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 若此 Bean 已經在 targetSourcedBeans 裡,說明已經被代理過,那就直接返回即可
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        // 如果該 Bean 是基礎框架 Bean 或者免代理的 Bean,那也不處理
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        // 邏輯同上,對於實現了 Advice,Advisor,AopInfrastructureBean 介面的 bean,都認為是 spring aop 的基礎框架類,不能對它們建立代理物件,
        // 同時子類也可以覆蓋 shouldSkip 方法來指定不對哪些 Bean 進行代理
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        // getAdvicesAndAdvisorsForBean 該方法由子類實現,如果有 Advice 切面切進去了,我們就要給它代理
        // 根據 getAdvicesAndAdvisorsForBean() 方法的具體實現的不同,AbstractAutoProxyCreator 又分成了兩類自動代理機制
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) { // 需要代理,那就進來給它建立一個代理物件
            this.advisedBeans.put(cacheKey, Boolean.TRUE); // 快取起來,賦值為 true,說明此 key 是被代理了的
            // 建立這個代理物件
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass()); // 建立好後快取起來,避免重複建立
            return proxy;
        }
        // 把不需要代理的物件也給與快取起來,賦值為 false
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    /**
     * 建立代理物件,specificInterceptors:作用在這個 Bean 上的增強器們
     * 這裡需要注意的地方:入參是 targetSource,而不是 target
     * 所以最終代理的是`每次 AOP 代理處理方法呼叫時,目標例項都會用到 TargetSource 實現`
     */
    protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }
        // 建立代理物件的三大方式之一
        ProxyFactory proxyFactory = new ProxyFactory();
        // 複製當前類的相關配置,因為當前類它也是個 ProxyConfig
        proxyFactory.copyFrom(this);

        // 看看是否是基於類的代理(CGLIB),若表面上是基於介面的代理,我們還需要進一步去檢測
        if (!proxyFactory.isProxyTargetClass()) {
            // shouldProxyTargetClass 方法用於判斷是否應該使用 targetClass 類而不是介面來進行代理
            // 預設實現為和該 Bean 定義是否屬性值 preserveTargetClass 為 true 有關。預設情況下都不會有此屬性值的
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            } else {
                // 到此處,就是把這個類實現的介面們,都放進 proxyFactory(當然也會處理一些特殊的介面,不算數的)
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        // buildAdvisors:整理合並得到最終的 advisors(畢竟 interceptorNames 還指定了一些攔截器的)
        // 至於呼叫的先後順序,通過 applyCommonInterceptorsFirst 引數可以進行設定,若 applyCommonInterceptorsFirst 為 true,interceptorNames 屬性指定的 Advisor 優先呼叫。預設為 true
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors); // 新增進工廠裡
        proxyFactory.setTargetSource(targetSource); // 把 targetSource 放進去,TargetSource 的實現方式有多種
        // 這個方法是交給子類的,子類可以繼續去定製此 proxyFactory(Spring 內部並沒重寫,為空方法)
        customizeProxyFactory(proxyFactory);

        // 沿用 this 的 freezeProxy 屬性值
        proxyFactory.setFrozen(this.freezeProxy);
        // 設定 preFiltered 的屬性值,預設是 false。子類:AbstractAdvisorAutoProxyCreator 修改為 true
        // preFiltered 欄位意思為:是否已為特定目標類篩選 Advisor
        // 這個欄位和 DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice 獲取所有的 Advisor 有關
        // CglibAopProxy 和 JdkDynamicAopProxy 都會呼叫此方法,然後遞迴執行所有的 Advisor
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        // getProxyClassLoader():呼叫者可指定,否則為:ClassUtils.getDefaultClassLoader()
        return proxyFactory.getProxy(getProxyClassLoader());
    }

AbstractAutoProxyCreator#createProxy 方法中呼叫了 AbstractAutoProxyCreator#buildAdvisors 方法

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
        // 解析 interceptorNames 而來的 Advisor 陣列
        Advisor[] commonInterceptors = resolveInterceptorNames();
        // 此處用的是 Object
        List<Object> allInterceptors = new ArrayList<>();
        if (specificInterceptors != null) {
            allInterceptors.addAll(Arrays.asList(specificInterceptors));
            if (commonInterceptors.length > 0) { // 若有內容
                if (this.applyCommonInterceptorsFirst) { // 放在頭部
                    allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
                } else { // 放在末尾
                    allInterceptors.addAll(Arrays.asList(commonInterceptors));
                }
            }
        }
        if (logger.isTraceEnabled()) {
            int nrOfCommonInterceptors = commonInterceptors.length;
            int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
            logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
        }
        // 把每一個 Advisor 都用 advisorAdapterRegistry.wrap() 包裝一下
        Advisor[] advisors = new Advisor[allInterceptors.size()];
        for (int i = 0; i < allInterceptors.size(); i++) {
            // wrap 方法預設只支援三種類型的 Advice 轉換為 Advisor
            advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
        }
        return advisors;
    }

    // 處理 interceptorNames,去容器內找出來
    private Advisor[] resolveInterceptorNames() {
        BeanFactory bf = this.beanFactory;
        ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
        List<Advisor> advisors = new ArrayList<>();
        for (String beanName : this.interceptorNames) {
            // 排除一些情況:此工廠不是 ConfigurableBeanFactory 或者該 Bean 不在建立中
            if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
                Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
                // 拿到這個 Bean,然後使用 advisorAdapterRegistry 把它適配一下即可
                Object next = bf.getBean(beanName);
                advisors.add(this.advisorAdapterRegistry.wrap(next));
            }
        }
        return advisors.toArray(new Advisor[0]);
    }

所有的建立器都是 AbstractAutoProxyCreator 該抽象類的子類,AbstractAutoProxyCreator 相當於一個代理建立的模版,規定了一些步驟。獲取 Advisor 的 getAdvicesAndAdvisorsForBean 由各子類自己去實現。

根據對 getAdvicesAndAdvisorsForBean() 的實現不一樣,策略有兩種。有兩個直接實現:BeanNameAutoProxyCreator 和 AbstractAdvisorAutoProxyCreator。

代理建立器可以分為三類:

  • 基於 Bean 配置名規則的自動代理生成器:允許為一組特定配置名的 Bean 自動建立代理例項的代理建立器,實現類為 BeanNameAutoProxyCreator
  • 基於 Advisor 匹配機制的自動代理建立器它會對容器中的所有 Advisor 進行掃描,自動將這些切面應用到匹配的 Bean 中,實現類是 DefaultAdvisorAutoProxyCreator(也支援字首匹配)
  • 基於 Bean 中 AspectJ 註解的自動代理生成器:為包含 AspectJ 註解的切入的 Bean 自動建立代理例項

先看BeanNameAutoProxyCreator

/**
 * 此時採用了 BeanNameAutoProxyCreator,自然就不用再 @EnableAspectJAutoProxy,自然 @Aspect 切面也就不生效了。
 * 當然,也可以開啟的,這樣他倆就聯合生效了(但不太建議去這麼使用)
 */
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
    BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
    // 給所有以 serviceImpl 結尾的類建立代理物件(支援正則),備註:aliases 也是被支援的
    // 注意此處若只寫`*Service`是匹配不上 helloServiceImpl
    beanNameAutoProxyCreator.setBeanNames("*ServiceImpl");

    // 備註:它要想使用攔截,只能通過 setInterceptorNames,從容器內拿 Advice 的實現類(自己書寫)
    beanNameAutoProxyCreator.setInterceptorNames("logMethodBeforeAdvice");
    return beanNameAutoProxyCreator;
}

需要注意的是:如果一個物件被切多次(使用 @Async、事務都會建立代理物件),最終這個物件代理會是多層代理。

如果想用自己註冊的 Bean 代替 @EnableAspectJAutoProxy 預設註冊的自動建立器,可以註冊 Bean 名稱為:AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME

/**
 * @since 10.10.2003
 */
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {

    @Nullable
    private List<String> beanNames;

    public void setBeanNames(String... beanNames) {
        Assert.notEmpty(beanNames, "'beanNames' must not be empty");
        this.beanNames = new ArrayList<>(beanNames.length);
        for (String mappedName : beanNames) {
            // 對 mappedName 做取出空白處理
            this.beanNames.add(StringUtils.trimWhitespace(mappedName));
        }
    }

    /**
     * BeanNameAutoProxyCreator 的此方法並沒有去尋找 Advisor,需要攔截的話,只能依靠:setInterceptorNames() 來指定攔截器。它是根據名字去 Bean 容器裡取的
     */
    @Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        if (this.beanNames != null) {
            for (String mappedName : this.beanNames) {
                // 如果針對的是 FactoryBean,也是相容的
                if (FactoryBean.class.isAssignableFrom(beanClass)) {
                    if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
                        continue;
                    }
                    // 對 BeanName 進行處理,去除掉第一個字元
                    mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
                }
                if (isMatch(beanName, mappedName)) { // 匹配就返回 PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS,而不是再返回 null
                    return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
                }
                // 如果存在 Bean 工廠,哪怕任意一個 alias 匹配都是可以的
                BeanFactory beanFactory = getBeanFactory();
                if (beanFactory != null) {
                    String[] aliases = beanFactory.getAliases(beanName);
                    for (String alias : aliases) {
                        if (isMatch(alias, mappedName)) {
                            return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
                        }
                    }
                }
            }
        }
        return DO_NOT_PROXY;
    }

    protected boolean isMatch(String beanName, String mappedName) {
        // simpleMatch 並不是完整的正則。但是支援 * 這種萬用字元,其餘的不支援
        return PatternMatchUtils.simpleMatch(mappedName, beanName);
    }
}

DefaultAdvisorAutoProxyCreator

類似 BeanNameAutoProxyCreator 的加強版,Spring 可以完成自動匹配的工作

/**
 * 類似 BeanNameAutoProxyCreator 的加強版
 */
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    return new DefaultAdvisorAutoProxyCreator();
}

/**
 * DefaultAdvisorAutoProxyCreator 還需要對應的 Advisor(可以有多個),從而給能夠匹配上的建立代理物件了
 */
@Bean
public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor() {
    NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor = new NameMatchMethodPointcutAdvisor();

    // 攔截到了 HelloService#hello() 方法,因此會給他建立代理物件
    nameMatchMethodPointcutAdvisor.addMethodName("*hello");

    // 此處雖然 HelloController(子容器裡) 有個方法名叫 helloGet,但是不會建立代理得。
    // 因為 NameMatchMethodPointcutAdvisor 在根容器裡,不作用於子容器的 Bean
    nameMatchMethodPointcutAdvisor.addMethodName("helloGet");
    nameMatchMethodPointcutAdvisor.setAdvice(new LogMethodBeforeAdvice());
    return nameMatchMethodPointcutAdvisor;
}

這樣它就會自動的去把 Advisor 匹配上的 Bean 進行代理掉。(不像 BeanNameAutoProxyCreator 還得手動指定 BeanName,以及攔截器們),一般都需要自己向容器注入自己的 Advisor,比如 NameMatchMethodPointcutAdvisor,否則它也不知道去代理誰。只有被對應的 Advisor 匹配上的才會生成代理物件。

AbstractAdvisorAutoProxyCreator

另一類自動代理方式,和 Advisor 有關(只有被切入的類,才會給它建立一個代理類),它的核心方法是實現了父類的:getAdvicesAndAdvisorsForBean 來獲取 Advisor

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

    @Nullable
    private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);
        // 重寫 setBeanFactory 方法,保證 bean 工廠是 ConfigurableListableBeanFactory
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        // 對 advisorRetrievalHelper 進行初始化,找 advisor 最終是委託給它了
        initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    }

    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
    }

    private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {
        public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
            super(beanFactory);
        }
        @Override
        protected boolean isEligibleBean(String beanName) {
            return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
        }
    }

    /**
     * 這是複寫父類的方法,也是實現代理方式。找到作用在這個 Bean 裡面的切點方法
     * 當然,最終最終是委託給 BeanFactoryAdvisorRetrievalHelper 去做的
     */
    @Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        // findEligibleAdvisors:這個是具體的實現方法了。
        // eligible:合格的、合適的
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    /**
     * 找出合適的 Advisor
     */
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 首先找出所有候選的 Advisors,(根據名字判斷)
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 對上面找到的候選的 Advisors 進行過濾操作,看看 Advisor 能否被用在 Bean 上(根據 Advisor 的 PointCut 判斷)
        // 主要依賴於 AopUtils.findAdvisorsThatCanApply() 方法
        // 邏輯簡單概述為:看目標類是不是符合代理物件的條件,如果符合就把 Advisor 加到集合中,最後返回集合
        // 簡單的說:它就是會根據 ClassFilter 和 MethodMatcher 等各種匹配。(但凡有一個方法被匹配上了,就會給它建立代理類)
        // 方法用的 ReflectionUtils.getAllDeclaredMethods,因此就算是私有方法,匹配上都會給建立代理物件
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        // 提供一個鉤子。子類可以複寫此方法,然後對 eligibleAdvisors 進行處理(增加/刪除/修改等等)
        // AspectJAwareAdvisorAutoProxyCreator 提供了實現
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) { // 如果最終還有,就排序
            // 預設排序方式:AnnotationAwareOrderComparator.sort() 排序,這個排序和 Order 介面有關
            // 子類 AspectJAwareAdvisorAutoProxyCreator 有複寫此排序方法,需要注意
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

    /**
     * 找到候選的 Advisor,抽象類自己的實現,是直接把這件事委託給了 advisorRetrievalHelper
     * AnnotationAwareAspectJAutoProxyCreator 對它有複寫
     */
    protected List<Advisor> findCandidateAdvisors() {
        Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

    /**
     * 判斷給定的 BeanName 這個 Bean,是否是合格的(BeanFactoryAdvisorRetrievalHelper 裡會用到這個屬性)
     * 其中:DefaultAdvisorAutoProxyCreator 和 InfrastructureAdvisorAutoProxyCreator 有複寫
     */
    protected boolean isEligibleAdvisorBean(String beanName) {
        return true;
    }

    @Override
    protected boolean advisorsPreFiltered() {
        return true;
    }

AspectJAwareAdvisorAutoProxyCreator

主要來處理AspectJ切面

public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

    // 預設的排序器,不是根據 Order 來了,而是根據 @Afeter @Before 類似的標註來排序
    private static final Comparator<Advisor> DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();

    /**
     * 核心邏輯:重寫了排序,控制著最終的執行順序
     * 這個排序和`org.aspectj.util`提供的 PartialOrder 和 PartialComparable 有關
     */
    @Override
    protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
        List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
        for (Advisor advisor : advisors) {
            partiallyComparableAdvisors.add(PartiallyComparableAdvisorHolder(advisor, DEFAULT_PRECEDENCE_COMPARATOR));
        }
        List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
        if (sorted != null) {
            List<Advisor> result = new ArrayList<>(advisors.size());
            for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
                result.add(pcAdvisor.getAdvisor());
            }
            return result;
        } else {
            return super.sortAdvisors(advisors);
        }
    }

    /**
     * 這個就是對已有的 Advisor 做了一個擴充套件:
     * AspectJProxyUtils 這個工具類只有這一個方法(其實每次 addAspect() 的時候,都會呼叫此方法)
     * Capable:能幹的、有才華的
     * 它的作用:若存在 AspectJ 的 Advice,就會在 advisors 的第一個位置加入`ExposeInvocationInterceptor.ADVISOR` 這個 advisor
     */
    @Override
    protected void extendAdvisors(List<Advisor> candidateAdvisors) {
        AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
    }

    @Override
    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 相當於 AspectJPointcutAdvisor 的子類不要攔截、AspectJ 切面自己的所有方法不要去攔截
        for (Advisor advisor : candidateAdvisors) {
            if (advisor instanceof AspectJPointcutAdvisor &&
                    ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
                return true;
            }
        }
        // 父類返回的 false
        return super.shouldSkip(beanClass, beanName);
    }

AnnotationAwareAspectJAutoProxyCreator

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

    @Nullable
    private List<Pattern> includePatterns;

    /**
     * 唯一實現類:ReflectiveAspectJAdvisorFactory
     * 作用:基於 @Aspect 時,建立 Spring AOP 的 Advice
     * 裡面會對標註這些註解 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 的方法進行排序
     * 然後把他們都變成 Advisor(getAdvisors()方法)
     */
    @Nullable
    private AspectJAdvisorFactory aspectJAdvisorFactory;

    /**
     * 用來從 bean 容器,也就是 BeanFactory 中獲取所有使用了 @AspectJ 註解的 bean
     * 就是這個方法:aspectJAdvisorsBuilder.buildAspectJAdvisors()
     */
    @Nullable
    private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;


    /**
     * 支援自定義一個正則的模版,isEligibleAspectBean() 該方法使用此模版,從而決定使用哪些 Advisor
     */
    public void setIncludePatterns(List<String> patterns) {
        this.includePatterns = new ArrayList<>(patterns.size());
        for (String patternText : patterns) {
            this.includePatterns.add(Pattern.compile(patternText));
        }
    }

    // 可以自己實現一個 AspectJAdvisorFactory,否則用預設的 ReflectiveAspectJAdvisorFactory
    public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {
        Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
        this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    }

    @Override
    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 此處一定要記得呼叫 super.initBeanFactory(beanFactory);
        super.initBeanFactory(beanFactory);
        if (this.aspectJAdvisorFactory == null) {
            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
        }
        this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    }

    /**
     * 拿到所有的候選的 advisor。請注意:這裡沒有先呼叫了父類的 super.findCandidateAdvisors() 去容器裡找出來一些
     * 然後自己又通過 aspectJAdvisorsBuilder.buildAspectJAdvisors() 解析 @Aspect 的方法得到一些 Advisor
     */
    @Override
    protected List<Advisor> findCandidateAdvisors() {
        List<Advisor> advisors = super.findCandidateAdvisors();
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

    // 加了種類型,如果該 Bean 自己本身就是一個 @Aspect,那也認為是基礎元件,不要切了
    @Override
    protected boolean isInfrastructureClass(Class<?> beanClass) {
        return (super.isInfrastructureClass(beanClass) || (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
    }

    // 拿傳入的正則模版進行匹配(沒傳就返回 true,所有的 Advisor 都會生效)
    protected boolean isEligibleAspectBean(String beanName) {
        if (this.includePatterns == null) {
            return true;
        } else {
            for (Pattern pattern : this.includePatterns) {
                if (pattern.matcher(beanName).matches()) {
                    return true;
                }
            }
            return false;
        }
    }

    private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {
        public BeanFactoryAspectJAdvisorsBuilderAdapter(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
            super(beanFactory, advisorFactory);
        }

        @Override
        protected boolean isEligibleBean(String beanName) {
            return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
        }
    }
}

BeanFactoryAdvisorRetrievalHelper

AbstractAdvisorAutoProxyCreator 中使用的工具類,用來從容器中找出所有的 Advisor 類

public class BeanFactoryAdvisorRetrievalHelper {

    private static final Log logger = LogFactory.getLog(BeanFactoryAdvisorRetrievalHelper.class);

    private final ConfigurableListableBeanFactory beanFactory;

    // 本地做一個簡單的欄位快取
    @Nullable
    private volatile String[] cachedAdvisorBeanNames;

    public BeanFactoryAdvisorRetrievalHelper(ConfigurableListableBeanFactory beanFactory) {
        Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
        this.beanFactory = beanFactory;
    }

    public List<Advisor> findAdvisorBeans() {
        String[] advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            // 這裡不會例項化 FactoryBeans
            // 我們需要保留所有常規 bean,未初始化,以允許自動代理建立者應用於它們
            // 注意此處:連祖先容器裡面的 Bean 都會拿出來(這個方法平時我們也可以使用)
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
        if (advisorNames.length == 0) {
            return new ArrayList<>();
        }

        List<Advisor> advisors = new ArrayList<>();
        for (String name : advisorNames) {
            // isEligibleBean:表示這個 bean 是否是合格的,預設是 true
            // InfrastructureAdvisorAutoProxyCreator 和 DefaultAdvisorAutoProxyCreator 都對 isEligibleBean 複寫了
            if (isEligibleBean(name)) {
                // 如果當前 Bean 正在建立中,那就什麼也不做
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Skipping currently created advisor '" + name + "'");
                    }
                } else { // 否則就把這個 Advisor 加入到 List 裡,是個合法的
                    try {
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    } catch (BeanCreationException ex) {
                        Throwable rootCause = ex.getMostSpecificCause();
                        if (rootCause instanceof BeanCurrentlyInCreationException) {
                            BeanCreationException bce = (BeanCreationException) rootCause;
                            String bceBeanName = bce.getBeanName();
                            if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                                if (logger.isTraceEnabled()) {
                                    logger.trace("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage());
                                }
                                continue;
                            }
                        }
                        throw ex;
                    }
                }
            }
        }
        return advisors;
    }

    protected boolean isEligibleBean(String beanName) {
        return true;
    }
}

Advisor(Advice + Pointcut) 建立過程

Advisor 中的 Pointcut 與 Advice 都是由 ReflectiveAspectJAdvisorFactory 來解析生成的

與之對應的 Advice 是 AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice、AspectJAroundAdvice

與之對應的 Pointcut 則是 AspectJExpressionPointcut

解析的步驟是:

  1. 自動代理建立器:AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()
  2. Bean工廠相關的Advisor構建器:BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()
  3. ReflectiveAspectJAdvisorFactory.getAdvisors()
  4. ReflectiveAspectJAdvisorFactory.getAdvisor() 最終生成了 InstantiationModelAwarePointcutAdvisorImpl(包括裡面的 Pointcut 與 Advice 也都是由 ReflectiveAspectJAdvisorFactory 解析生成的)


https://blog.csdn.net/f641385712/article/details/88904864

https://blog.csdn.net/f641385712/article/details/88904983

https://javadoop.com/post/spring-aop-source