Spring源碼解析之AOP篇

什么是AOP?

AOP(Aspect Oriented Programming):面向切面編程,與面向對象編程OOP的關鍵單位是類不一樣,它的關鍵單位是切面,它通過提供改變程序結構的方式來補充OOP。通俗點就是說我們可以通過預編譯或者運行時動態(tài)代理在不修改方法源碼的情況下增強方法的功能。

實際開發(fā)中,AOP的出現(xiàn)方便了業(yè)務需求和系統(tǒng)功能之間的解耦和擴展,比如日志、事務、安全、權限等等系統(tǒng)功能,大大減少了重復的代碼,以及維護的復雜,提高了開發(fā)效率。

而AOP的這種解決方式的本質就是代理機制。

準備工作

之前解析Spring源碼或者在實際開發(fā)過程中,相信或多或少都對AOP代理有一些認識,那么在接下來解析源碼前,我們需要先對一些相關基礎作更全面的了解。

基礎概念

切面(Aspect):介紹切面之前,我們先了解切面里面的連接點(JoinPoin),一個連接點就是代表一個類的執(zhí)行方法;而切面就是連接多個類的連接點的一個橫切面(官文稱為跨越多個類的關注點的模塊化模塊化)。通常使用@Aspect注解聲明的就是一個切面。

切點(Pointcut):切面中所有連接點匹配的規(guī)則定義,由多種切點表達式定義,而Spring AOP支持以下j幾種切點表達式,

  • execution: 匹配方法執(zhí)行的任何連接點。

  • within:匹配指定類型內的方法執(zhí)行的任何連接點。

  • this: 匹配代理實現(xiàn)指定類型接口的任何連接點。

  • target: 匹配目標對象實現(xiàn)指定類型接口的任何連接點。

  • args: 匹配指定類型參數(shù)的方法執(zhí)行的連接點。

  • @target: 匹配目標對象實現(xiàn)指定類型接口的具有指定注解的任何連接點。

  • @args:匹配指定類型參數(shù)的具有指定注解的方法執(zhí)行的連接點。

  • @within: 匹配指定類型內的具有指定注解的方法執(zhí)行的任何連接點。

  • @annotation:匹配指定注解的方法執(zhí)行的連接點。

    其中execution和@annotation在實際開發(fā)中可能更為常用,至于不同表達式的書寫規(guī)則請參考具體的官方文檔說明。

通知:匹配的切點周圍的攔截器方法,Spring中包括一下幾種不同類型的通知,

  • 前置通知:方法執(zhí)行的攔截。
  • 后置通知:方法執(zhí)行后的攔截,無論正常返回還是異常退出。
  • 返回通知:方法正常執(zhí)行完的攔截。
  • 環(huán)繞通知:方法執(zhí)行時前后的自定義攔截,手動控制調用的方法。
  • 異常通知:方法執(zhí)行時異常退出的攔截。

目標對象:被一個或者多個切面通知的對象,它始終是一個被代理的對象。

使用方式

Spring中有兩種配置使用AOP的方式,分別是:

  • 基于XML的配置:配置繁瑣,不同的需求集中配置不符合單一職責原則,無法組合聲明的命名切入點。
  • 基于@Aspect的注解:配置簡單,支持更豐富的配置組合,同時具有單元模塊化。這也是開發(fā)中主要的使用方式。

代理機制

Spring中的代理機制分為兩種:

  • JDK動態(tài)代理:內置在JDK中,通過攔截和反射來實現(xiàn),被代理的對象必須要實現(xiàn)接口。
  • CGLIB動態(tài)代理:一個開源類的定義庫,通過ASM字節(jié)碼生成的方式生成代理類,默認代理沒有實現(xiàn)的接口的對象,不能對final修飾的方法進行代理;Spring中可以通過設置@EnableAspectJAutoProxy(proxyTargetClass = true)強制使用用CGLIB進行動態(tài)代理。

調用流程

了解完上述一些相關基礎之后,接下來我們將會從源碼來分析AOP的初始化到實際調用的過程。

而完成AOP的初始化其實也是穿插在IOC容器的初始化過程中,前面我們已經了解過IOC容器,包括依賴注入的初始化過程,再來看AOP的相關源碼應該是更加容易下手的,同時這也是對之前內容的補充。

這里我們主要以注解的方式來使用并分析源碼過程。

首先我們寫個簡單的測試類來看下AOP的使用和應用效果,

@Configuration
@EnableAspectJAutoProxy
public class Config {
}

@Component
public class AopA{
    public void print(){
        System.out.println("AAAAAAAAAAAAAA");
    }
}

@Aspect
@Component
public class AspectA {

    @Pointcut("execution(* com.test.spring.entity.AopA.*(..))")
    public void point(){
    }

    @Before("point()")
    public void before(){
        System.out.println("before");
    }

    @After("point()")
    public void after() throws Exception {
        System.out.println("after");
    }

    @Around("point()")
    public void around(JoinPoint joinPoint){
        System.out.println("aroundBefore");
        try {
            ((ProceedingJoinPoint)joinPoint).proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("aroundAfter");
    }

    @AfterReturning("point()")
    public void afterReturn(){
        System.out.println("afterReturn");
    }

    @AfterThrowing("point()")
    public void afterThrow(){
        System.out.println("afterThrow");
    }

}

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext("com.test.spring");
        AopA aopA = ac.getBean(AopA.class);
        aopA.print();
    }

}

運行代碼,控制臺打印如下,

aroundBefore
before
AAAAAAAAAAAAAA
aroundAfter
after
afterReturn

如果方法執(zhí)行過程中拋出異常,則會打印配置的異常通知中的afterThrow

啟用自動代理

Spring內置了很多豐富且強大的功能,但是并不是每個功能都是默認開啟的,比如AOP自動代理,我們首先得告訴Spring容器去啟用自動代理,這樣它才會掃描、注冊、應用我們配置的相關注解類。而通過注解的方式啟用自動代理也很簡單,就是通過上面測試類中配置的@EnableAspectJAutoProxy注解來啟用。

還是從0到1,我們就從@EnableAspectJAutoProxy注解來入手。

我們先看下這個注解的源碼,

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;
}

其中類上加了一個注解@Import({AspectJAutoProxyRegistrar.class}),而我們知道@Import注解代表AspectJAutoProxyRegistrar對象可以通過配置的@EnableAspectJAutoProxy注解的類去加載,也就是說IOC實例化Config對象的時候也會實例化AspectJAutoProxyRegistrar。

同時這里我們也能看到EnableAspectJAutoProxy具有兩個配置屬性,

  • proxyTargetClass:默認false,Spring會根據(jù)被代理對象的實現(xiàn)接口情況去自動選擇JDK或者CGLIB動態(tài)代理機制;設置為true時,代表代理機制強制使用CGLIB動態(tài)代理,但這樣會導致無法對final修飾的方法進行攔截通知,因為它不能被覆寫。
  • exposeProxy:是否暴露當前代理對象為 ThreadLocal以便目標可以訪問它。比如方法a()、b()都被攔截通知,默認false時,方法a()中調用b()方法的話,則調用的方法b()不會被攔截通知,如果設置為true時,調用的方法b()也會被攔截通知。

后過頭來,我們繼續(xù)分析下配置完啟動注解之后會發(fā)生什么?以及AspectJAutoProxyRegistrar類的作用。那我們就又要從IOC容器的初始化開始說了,首先我們這里的測試類都是基于Annotation來完成IOC容器的初始化。前面IOC源碼解析中,我們已經知道第一步會調用scan()方法來掃描配置的指定包路徑下的所有Bean對象,并封裝成BeanDefinition對象存放beanDefinitionMap中,之后會調用refresh()方法去載入Bean的配置資源,而這里主要先關注其中的兩個方法,分別是,

//實例化并調用所有已注冊的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
//注冊BeanPost事件處理器
registerBeanPostProcessors(beanFactory);

我們先看invokeBeanFactoryPostProcessors(),通過注釋大概知道它的作用了,那我們來看看源碼,

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

我們能看出真正的實現(xiàn)是委托PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors()來完成的,

    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        Set<String> processedBeans = new HashSet<>();
         // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }
            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }
            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }
        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }
        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

一眼望去感覺實現(xiàn)的邏輯相當繁瑣復雜,其實你細看發(fā)現(xiàn)很多代碼處理幾乎是重復的,先獲取postProcessorNames的數(shù)組,然后遍歷調用getBean()實例化并添加到currentRegistryProcessors臨時集合中,接著傳參到invokeBeanFactoryPostProcessors()并調用,最后clear()臨時集合。這里面主要是將實現(xiàn) PriorityOrdered、Ordered 和其余的 BeanDefinitionRegistryPostProcessor 分開處理。首先會實例化并調用實現(xiàn)PriorityOrdered接口ConfigurationClassPostProcessor,它是用來引導處理配置類(配置@Configuration的類),比如配置@Configuration,通常是會默認注冊的,也可以使用任何其他 BeanFactoryPostProcessor 去手動聲明,它會在任何其他 BeanFactoryPostProcessor 執(zhí)行之前注冊了配置類中聲明的Bean定義。我們之前在配置@EnableAspectJAutoProxy的類上也加了@Configuration注解的作用也是因為這個。

其實分析到這里,接下來的流程處理可能就已經柳暗花明了,再往下調用的源碼牽扯的細節(jié)比較多,而且繼續(xù)貼源碼也會顯得比較繁瑣不容易抓住主流程,這里不一一展開了,我會用時序圖來展示后面的流程,

image

最終就是為了通過AspectJAutoProxyRegistrar的registerBeanDefinitions()方法把對象AnnotationAwareAspectJAutoProxyCreator封裝成BeanDefinition并注冊到容器中去,同時將proxyTargetClass和exposeProxy的屬性值注入進去。

注冊后置處理器

那我們?yōu)槭裁磫觾H僅是通過配置類最終把AnnotationAwareAspectJAutoProxyCreator注冊到容器中去呢?其實我們看下它的類圖結構就知道了,

image-20210811101949856

它實現(xiàn)了BeanPostProcessor接口,我們看下它的源碼,

public interface BeanPostProcessor {
    //Bean的初始化前回調
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    //Bean的初始化之后回調
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

而我們知道BeanPostProcessor的作用是:定義了Bean的初始化回調方法,在其實例化、配置和初始化之后實現(xiàn)一些自定義邏輯。你可以理解為Bean對象的攔截器,如果你想擴展Bean的功能或對其修改包裝等,就可以通過實現(xiàn)它去完成。所以AnnotationAwareAspectJAutoProxyCreator的作用就很清楚了,它就是為了在Bean初始化之后對其做一些自定義的處理,至于怎么樣的處理我們后面細講。

但是這里只是將它注冊到容器中去,我們還需要把它實例化并添加到集合List<BeanPostProcessor> beanPostProcessors中去,所以上面的registerBeanPostProcessors()方法就是完成這個事的,

    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }

同樣真正的實現(xiàn)還是交給PostProcessorRegistrationDelegate去完成的,

    public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }
        // First, register the BeanPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
        // Next, register the BeanPostProcessors that implement Ordered.
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);
        // Now, register all regular BeanPostProcessors.
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
        // Finally, re-register all internal BeanPostProcessors.
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);
        // Re-register post-processor for detecting inner beans as ApplicationListeners,
        // moving it to the end of the processor chain (for picking up proxies etc).
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

    private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors){
        for (BeanPostProcessor postProcessor : postProcessors) {
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        this.beanPostProcessors.remove(beanPostProcessor);
        this.beanPostProcessors.add(beanPostProcessor);
        if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
            this.hasInstantiationAwareBeanPostProcessors = true;
        }
        if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
            this.hasDestructionAwareBeanPostProcessors = true;
        }
    }

我們能看到這里就是將實現(xiàn) PriorityOrdered、Ordered 和其余的 BeanDefinitionRegistryPostProcessor 的BeanPostProcessor分開添加到集合beanPostProcessors中;而我們知道AnnotationAwareAspectJAutoProxyCreator是Ordered的子類,這里我們主要看對orderedPostProcessorNames的處理:

  1. 首先會遍歷orderedPostProcessorNames集合,拿到AnnotationAwareAspectJAutoProxyCreator;
  2. 然后調用getBean()方法對其實例化;
  3. 完成之后調用registerBeanPostProcessors()將AnnotationAwareAspectJAutoProxyCreator添加到BeanPostProcessor的集合中去。

其實到這里才會最終完成自動代理的配置的生效啟用,接下來我們應該也能猜到,將會通過配置的切面類來對匹配規(guī)則的目標Bean在其初始化之后對其做代理的相應處理。

解析@Aspect切面配置

做完上面的這些之后,我們知道IOC容器接下來會調用finishBeanFactoryInitialization()方法對容器中的單例Bean進行預實例化,也就是依賴注入的過程了。

那接下來是怎么解析配置的切面類以及其中定義的切點和通知呢(也就是解析我們配置的AspectA類)?

我們繼續(xù)來分析,我們知道在創(chuàng)建Bean之前,會調用resolveBeforeInstantiation()方法來應用解析Bean配置的實例化前后處理器,

    @Nullable
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

    @Nullable
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

也是就會遍歷之前集合添加的BeanPostProcessor并調用父類是InstantiationAwareBeanPostProcessor的子類實現(xiàn)的postProcessBeforeInstantiation()方法,從上面類圖中我們知道,之前添加的AnnotationAwareAspectAutoProxyCreator就是它的子類,而這里真正調用的是AnnotationAwareAspectAutoProxyCreator的父類AbstractAutoProxyCreator的方法實現(xiàn),

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        Object cacheKey = getCacheKey(beanClass, beanName);
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }
        //存在自定義的TargetSource則創(chuàng)建代理
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        return null;
    }

這里先來看下isInfrastructureClass()方法,

    protected boolean isInfrastructureClass(Class<?> beanClass) {
        boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
                Pointcut.class.isAssignableFrom(beanClass) ||
                Advisor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass);
        if (retVal && logger.isTraceEnabled()) {
            logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
        }
        return retVal;
    }

它會判斷當前的Bean是否是不能代理的基礎設施類,比如Advice、PointCut、Advisor等接口的實現(xiàn)類;這里其實就是來篩選我們測試代碼中的切面配置類AspectA,并將它放到Map<Object, Boolean> advisedBeans緩存中。

同時還會調用shouldSkip()方法判斷當前Bean是否應該跳過,這里面就關系著配置@Aspect注解的切面類的配置的提前解析,而這實際委托的是子類AspectJAwareAdvisorAutoProxyCreator實現(xiàn)的,我們往下看,

    @Override
    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        for (Advisor advisor : candidateAdvisors) {
            if (advisor instanceof AspectJPointcutAdvisor) {
                if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                    return true;
                }
            }
        }
        return super.shouldSkip(beanClass, beanName);
    }

這里面實現(xiàn)很簡單,就是調用findCandidateAdvisors()方法獲取通知Advisor的集合,然后遍歷Advisor去檢查配置Pointcurt切點的類的beanName是否和當前Bean的beanName一致,一致則返回true,否則調用父類的shouldSkip()獲取默認的false實現(xiàn)。

我們重點需要看的是findCandidateAdvisors()方法,這里實際調用的是AnnotationAwareAspectJAutoProxyCreator中實現(xiàn),

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

發(fā)現(xiàn)原來是對父類方法的增強,它有個很重要的作用:既保留了父類的獲取xml配置文件定義的通知外,又增加了獲取注解配置的通知。由于我們是通過注解去配置的,我們直接看由aspectJAdvisorsBuilder的buildAspectJAdvisors()方法實現(xiàn)就行,至于findCandidateAdvisors()中的實現(xiàn)感興趣可以自己研究下,你會發(fā)現(xiàn)其實兩種的實現(xiàn)代碼都大同小異,

    public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = this.aspectBeanNames;
        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    List<Advisor> advisors = new LinkedList<>();
                    aspectNames = new LinkedList<>();
                      // 獲取容器中注冊的所有beanName
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    for (String beanName : beanNames) {
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
                        // We must be careful not to instantiate beans eagerly as in this case they
                        // would be cached by the Spring container but would not have been weaved.
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                          //判斷Bean是否有@Aspect注解
                        if (this.advisorFactory.isAspect(beanType)) {
                            aspectNames.add(beanName);
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                   //獲取配置的通知方法集合
                                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                                if (this.beanFactory.isSingleton(beanName)) {
                                    this.advisorsCache.put(beanName, classAdvisors);
                                }
                                else {
                                    this.aspectFactoryCache.put(beanName, factory);
                                }
                                advisors.addAll(classAdvisors);
                            }
                            else {
                                // Per target or per this.
                                if (this.beanFactory.isSingleton(beanName)) {
                                    throw new IllegalArgumentException("Bean with name '" + beanName +
                                            "' is a singleton, but aspect instantiation model is not singleton");
                                }
                                MetadataAwareAspectInstanceFactory factory =
                                        new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                                this.aspectFactoryCache.put(beanName, factory);
                                advisors.addAll(this.advisorFactory.getAdvisors(factory));
                            }
                        }
                    }
                    this.aspectBeanNames = aspectNames;
                    return advisors;
                }
            }
        }
        if (aspectNames.isEmpty()) {
            return Collections.emptyList();
        }
         //緩存通知方法
        List<Advisor> advisors = new LinkedList<>();
        for (String aspectName : aspectNames) {
            List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
            if (cachedAdvisors != null) {
                advisors.addAll(cachedAdvisors);
            }
            else {
                MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }
        return advisors;
    }

這個方法的實現(xiàn)流程如下:

  1. 獲取容器中注冊的所有beanName;
  2. 遍歷所有beanName,并找到配置@Aspect注解的切面類;
  3. 解析獲取切面類中配置的通知方法;
  4. 緩存最后獲取的通知方法。

而其中通知方法的解析是交給ReflectiveAspectJAdvisorFactory的getAdvisors()方法是實現(xiàn)的,

    @Override
    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        validate(aspectClass);
        // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
        // so that it will only instantiate once.
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
        List<Advisor> advisors = new LinkedList<>();
         // 遍歷配置@Pointcut的方法
        for (Method method : getAdvisorMethods(aspectClass)) {
             //獲取配置切面的通知方法
            Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
        // If it's a per target aspect, emit the dummy instantiating aspect.
        if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }
        // Find introduction fields.
        for (Field field : aspectClass.getDeclaredFields()) {
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        return advisors;
    }

這里有兩個重要方法:一個是getAdvisorMethods(),獲取切面類中配置@Pointcut的方法,

    private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        final List<Method> methods = new LinkedList<>();
        ReflectionUtils.doWithMethods(aspectClass, method -> {
            // Exclude pointcuts
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        });
        Collections.sort(methods, METHOD_COMPARATOR);
        return methods;
    }

一個是getAdvisor(),獲取配置切點@Pointcut的幾種通知方法(Before、Around、After、AfterReturning、 AfterThrowing),

    @Override
    @Nullable
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {
        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }
         //封裝切點和通知方法信息
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

    @Nullable
    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }
         //封裝對象
        AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        //獲取切點表達式
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        if (this.beanFactory != null) {
            ajexp.setBeanFactory(this.beanFactory);
        }
        return ajexp;
    }

    @Nullable
    protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
        Class<?>[] classesToLookFor = new Class<?>[] {
                Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
        for (Class<?> c : classesToLookFor) {
            AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
            if (foundAnnotation != null) {
                return foundAnnotation;
            }
        }
        return null;
    }

這幾個方法的主要作用就是將獲取的切點及通知方法信息封裝成InstantiationModelAwarePointcutAdvisorImpl對象,同時這個對象里面定義了不同注解通知的實現(xiàn)策略(感興趣就可以看下實現(xiàn)類的源碼),分別是:

  • AspectJMethodBeforeAdvice
  • AspectJAfterAdvice
  • AspectJAfterReturningAdvice
  • AspectJAfterThrowingAdvice
  • AspectJAroundAdvice

后面調用相應通知的代理方法時就是由它們去處理實現(xiàn)的。

生成代理對象

完成上面的切面類的解析之后,那下一步肯定就需要根據(jù)定義的切點表達式篩選出目標類,并替換為生成的代理對象。

那我們繼續(xù)往下分析,我們知道在Bean創(chuàng)建完成后,會先進行屬性注入,再調用initializeBean()方法來初始化,而initializeBean()方法中會調用applyBeanPostProcessorsAfterInitialization()方法,來應用之前集合中添加的BeanPostProcessor后置處理器進行初始化處理回調,

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
        Object result = existingBean;
        //遍歷BeanPostProcessor后置處理器
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

能看到這里會遍歷BeanPostProcessor實現(xiàn)類,并調用其實現(xiàn)的postProcessAfterInitialization()方法,而這里我們主要關注的就是之前添加的AnnotationAwareAspectAutoProxyCreator,但是我們看它的源碼,是沒有這個方法的,其實具體的方法實現(xiàn)是在它的父類AbstractAutoProxyCreator中,

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if (bean != null) {
             //獲取緩存的beanName
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

這里先通過earlyProxyReferences來對beanName做緩存判斷,如果你了解過依賴注入中循環(huán)依賴的解決過程,你就知道這段代碼的作用:在對象Bean創(chuàng)建完成后,會先把這個對象的ObjectFactory的放到singletonFactories緩存中來讓有依賴的Bean提前拿到對象的引用,而這個就是ObjectFactory封裝的就是調用getEarlyBeanReference()返回的Bean,這個方法中也會遍歷BeanPostProcessor,并調用getEarlyBeanReference()方法,而它真正調用實現(xiàn)是在AbstractAutoProxyCreator中,

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            this.earlyProxyReferences.add(cacheKey);
        }
        return wrapIfNecessary(bean, beanName, cacheKey);
    }

是不是發(fā)現(xiàn)同樣的都會調用wrapIfNecessary()方法,所以這里緩存判斷的作用就很明顯了,就是為了防止重復調用wrapIfNecessary()方法。而這個方法也是我們重點去了解的,

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

是不是發(fā)現(xiàn)代碼很是熟悉,之前Bean實例化之前就已經提前處理過了并緩存了,我們直接看getAdvicesAndAdvisorsForBean()方法,

    @Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
         //獲取緩存的通知
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
         //獲取Bean匹配切點定義的通知
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

這里的作用比較容易理解,就是獲取之前緩存的Advisor的封裝InstantiationModelAwarePointcutAdvisorImpl類的集合,再匹配當前Bean滿足切點定義的通知,結束上層的方法,如果通知為空,則無需要對當前Bean進行代理,反正則會調用createProxy()方法創(chuàng)建當前Bean的代理對象。

我們來看createProxy()方法的實現(xiàn),

    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();
        proxyFactory.copyFrom(this);
         //判斷配置的proxyTargetClass
        if (!proxyFactory.isProxyTargetClass()) {
             //確定Bean是否應該用它的目標類而不是它的接口來代理
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                  //有接口則添加代理接口,沒有則設置proxyTargetClass為true
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
         //加入通知攔截器
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        return proxyFactory.getProxy(getProxyClassLoader());
    }

    public Object getProxy(@Nullable ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

方法的最后就是通過選擇不同的代理機制來創(chuàng)建代理類,主要就是JDK和CGLIB兩種動態(tài)代理機制,前文也已經簡要介紹過了它們的不同點,至于兩種代理機制更詳細的區(qū)別及實現(xiàn),有機會單獨再寫一篇了。

到此代理對象的生成就結束了。

調用代理方法

等IOC容器初始化完成之后,斷點一下你會發(fā)現(xiàn)所有被代理的對象的引用都是l類似這樣$Proxy27@2699,那么當我們調用其中被通知的方法會是怎樣一個流程呢?

以JDK動態(tài)代理機制為例,我們來探究下,首先會調用JdkDynamicAopProxy的invoke()方法,

    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;
        TargetSource targetSource = this.advised.targetSource;
        Object target = null;
        try {
            //判斷是否是eqauls()方法
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                return equals(args[0]);
            }
            //判斷是否是hashCode()方法
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                return hashCode();
            }
             //判斷是否是代理類
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            //判斷是否是Advised接口或者其父接口中定義的方法
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }
            Object retVal;
            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            //獲得目標對象
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);
            //獲取通知攔截器
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            if (chain.isEmpty()) {
                // 直接反射調用
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                //創(chuàng)建MethodInvocation
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                retVal = invocation.proceed();
            }
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

在方法中,先獲取代理類中的通知攔截器鏈,再調用ReflectiveMethodInvocation的proceed()方法;我們先看下getInterceptorsAndDynamicInterceptionAdvice()方法中是怎么把Advisor轉換成

    @Nullable
    public Object proceed() throws Throwable {
        //執(zhí)行完Interceptor則執(zhí)行joinPoint
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
        Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        //如果要動態(tài)匹配joinPoint
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            //匹配運行時參數(shù)
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                //調用下一個Interceptor
                return proceed();
            }
        }
        else {
            //執(zhí)行當前Intercetpor
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

這里的獲取的interceptorOrInterceptionAdvice其實就是之前說的幾種不同注解通知的策略類,分別會調用它們實現(xiàn)的invoke()方法(不同策略的方法實現(xiàn)可以去看看,這里就不貼源碼了),完成配置的通知方法內的自定義實現(xiàn),并且在完成前后會調用invokeJoinpoint()方法,而invokeJoinpoint()方法的本質就是直接通過反射調用被代理類中的目標方法。

到此Spring中完整的AOP實現(xiàn)過程就結束了。


把一件事做到極致就是天分!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容