Spring系列(五):Spring AOP源碼解析

1、@EnableAspectJAutoProxy註解

  在主配置類中添加@EnableAspectJAutoProxy註解,開啓aop支持,那麼@EnableAspectJAutoProxy到底作了什麼?接下來分析下:html

   @EnableAspectJAutoProxy點進去以下:git

   此時看到了咱們很是熟悉的@Import註解,@Import(AspectJAutoProxyRegistrar.class),進入到AspectJAutoProxyRegistrar發現實現了ImportBeanDefinitionRegistrar以下:spring

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

}

  會調用registerBeanDefinitions方法,跟進到這個方法裏面,主要做用就是往Spring容器中註冊AnnotationAwareAspectJAutoProxyCreator的Bean的定義信息:express

 2、AnnotationAwareAspectJAutoProxyCreator繼承圖

 3、AnnotationAwareAspectJAutoProxyCreator建立代理

  首先AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了BeanFactoryAware接口:

  因此在建立AnnotationAwareAspectJAutoProxyCreatorBean的過程當中初始化方法裏面會調用setBeanFactory方法:設計模式

   在setBeanFactory方法裏面調用initBeanFactory來初始化通知者檢索幫助類,後面檢索通知會用到。數組

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

   其次AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了InstantiationAwareBeanPostProcessor接口:

  該接口定義了2個方法:postProcessBeforeInstantiation和postProcessAfterInstantiation,因此AbstractAutoProxyCreator實現了這2個方法;還記得咱們在Spring IoC源碼解析篇分析到以下代碼:緩存

   resolveBeforeInstantiation方法進去就會調到AbstractAutoProxyCreator的postProcessBeforeInstantiation方法app

/**
     * 在建立Bean的流程中還沒調用構造器來實例化Bean的時候進行調用(實例化先後)
     * AOP解析切面以及事務解析事務註解都是在這裏完成的
     * @param beanClass 當前正在建立的Bean的Class對象
     * @param beanName beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        //構建咱們的緩存key
        Object cacheKey = getCacheKey(beanClass, beanName);

        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            //若是被解析過直接返回
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            /**
             * 判斷是否是基礎的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)是就直接跳過
             * 判斷是否是應該跳過 (AOP解析直接解析出咱們的切面信息(而且把咱們的切面信息進行緩存),而事務在這裏是不會解析的)
             */
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        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;
    }

  接下來進入到shouldSkip(beanClass, beanName)方法(很重要):ide

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
        /**
         * 找到候選的Advisors(通知者或者加強器對象)
         */
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        for (Advisor advisor : candidateAdvisors) {
            if (advisor instanceof AspectJPointcutAdvisor &&
                    ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
                return true;
            }
        }
        return super.shouldSkip(beanClass, beanName);
    }

  接下來看如何找候選的Advisors,findCandidateAdvisors()方法以下:post

@Override
    protected List<Advisor> findCandidateAdvisors() {
        //找出事務相關的advisor
        List<Advisor> advisors = super.findCandidateAdvisors();
        //找出Aspect相關的信息以後封裝爲一個advisor
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        //返回咱們全部的通知
        return advisors;
    }

  第一步找事務相關的Advisor:

protected List<Advisor> findCandidateAdvisors() {
        Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
        /**
         * 經過通知者檢測幫助類來幫助咱們找到通知
         *
         */
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

  第二步找構建AspectJAdvisors:

/**
     * 去容器中獲取到全部的切面信息保存到緩存中
     */
    public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = this.aspectBeanNames;
        //緩存字段aspectNames沒有值 注意實例化第一個單實例bean的時候就會觸發解析切面
        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    //用於保存全部解析出來的Advisors集合對象
                    List<Advisor> advisors = new ArrayList<>();
                    //用於保存切面的名稱的集合
                    aspectNames = new ArrayList<>();
                    /**
                     * AOP功能中在這裏傳入的是Object對象,表明去容器中獲取到全部的組件的名稱,而後再
                     * 進行遍歷,這個過程是十分的消耗性能的,因此說Spring會再這裏加入了保存切面信息的緩存。
                     * 可是事務功能不同,事務模塊的功能是直接去容器中獲取Advisor類型的,選擇範圍小,且不消耗性能。
                     * 因此Spring在事務模塊中沒有加入緩存來保存咱們的事務相關的advisor
                     */
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    //遍歷咱們從IOC容器中獲取處的全部Bean的名稱
                    for (String beanName : beanNames) {
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
                        //經過beanName去容器中獲取到對應class對象
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        //根據class對象判斷是否是切面 @Aspect
                        if (this.advisorFactory.isAspect(beanType)) {
                            //是切面類
                            //加入到緩存中
                            aspectNames.add(beanName);
                            //把beanName和class對象構建成爲一個AspectMetadata
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

                                //構建切面註解的實例工廠
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                //真正的去獲取咱們的Advisor
                                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 ArrayList<>(); 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; }

   ① org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#isAspect:

   ② 真正的去獲取咱們的Advisor,this.advisorFactory.getAdvisors(factory)方法以下:

@Override
    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        //獲取咱們的標記爲Aspect的類
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //獲取咱們的切面類的名稱
        String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        //校驗咱們的切面類
        validate(aspectClass);

        //咱們使用的是包裝模式來包裝咱們的MetadataAwareAspectInstanceFactory構建爲MetadataAwareAspectInstanceFactory
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

        List<Advisor> advisors = new ArrayList<>();
        //獲取到切面類中的全部方法,可是該方法不會解析到標註了@PointCut註解的方法
        for (Method method : getAdvisorMethods(aspectClass)) {
            //循環解析咱們切面中的方法
            Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }

        for (Field field : aspectClass.getDeclaredFields()) {
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        return advisors;
    }

   獲取切面上的通知方法,並按照規則排序,getAdvisorMethods(aspectClass):

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

  排序(該順序在代理調用的時候會用到)規則以下:

   根據通知的方法建立加強器:getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName)以下:

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);
    }

  實例化咱們的切面通知對象,new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName):

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
            Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

        //當前的切點表達式
        this.declaredPointcut = declaredPointcut;
        //切面的class對象
        this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
        //切面方法的名稱
        this.methodName = aspectJAdviceMethod.getName();
        //切面方法的參數類型
        this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
        //切面方法對象
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        //aspectj的通知工廠
        this.aspectJAdvisorFactory = aspectJAdvisorFactory;
        //aspect的實例工廠
        this.aspectInstanceFactory = aspectInstanceFactory;
        //切面的順序
        this.declarationOrder = declarationOrder;
        //切面的名稱
        this.aspectName = aspectName;

        /**
         * 判斷當前的切面對象是否須要延時加載
         */
        if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            // Static part of the pointcut is a lazy type.
            Pointcut preInstantiationPointcut = Pointcuts.union(
                    aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

            // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
            // If it's not a dynamic pointcut, it may be optimized out
            // by the Spring AOP infrastructure after the first evaluation.
            this.pointcut = new PerTargetInstantiationModelPointcut(
                    this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
            this.lazy = true;
        }
        else {
            // A singleton aspect.
            this.pointcut = this.declaredPointcut;
            this.lazy = false;
            //將切面中的通知構造爲advice通知對象
            this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        }
    }

  將切面中的通知構造爲advice通知對象,instantiateAdvice(this.declaredPointcut):

   獲取通知getAdvice方法以下:

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

        //獲取咱們的切面類的class對象
        Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        validate(candidateAspectClass);

        //獲取切面方法上的註解
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        //解析出來的註解信息是否爲null
        if (aspectJAnnotation == null) {
            return null;
        }

        //再次判斷是不是切面對象
        if (!isAspect(candidateAspectClass)) {
            throw new AopConfigException("Advice must be declared inside an aspect type: " +
                    "Offending method '" + candidateAdviceMethod + "' in class [" +
                    candidateAspectClass.getName() + "]");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Found AspectJ method: " + candidateAdviceMethod);
        }

        AbstractAspectJAdvice springAdvice;

        //判斷標註在方法上的註解類型
        switch (aspectJAnnotation.getAnnotationType()) {
            //是PointCut註解 那麼就拋出異常 由於在外面傳遞進來的方法已經排除了Pointcut的方法
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            //環繞通知 構建AspectJAroundAdvice
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            //前置通知  構建AspectJMethodBeforeAdvice
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            //後置通知 AspectJAfterAdvice
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            //返回通知 AspectJAfterReturningAdvice
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            //異常通知   AspectJAfterThrowingAdvice
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }

        //設置咱們構建出來的通知對象的相關屬性好比DeclarationOrder,在代理調用的時候,責任鏈順序上會用到
        springAdvice.setAspectName(aspectName);
        springAdvice.setDeclarationOrder(declarationOrder);
        String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
        if (argNames != null) {
            springAdvice.setArgumentNamesFromStringArray(argNames);
        }
        springAdvice.calculateArgumentBindings();

        return springAdvice;
    }

  至此真正的去獲取咱們的Advisor方法解析完成,List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

   ③ 若是該切面是單實例的就加入到緩存中:

   ④ 遍歷全部的切面,將每一個切面的全部的加強器添加在advisors中進行返回:

   AbstractAutoProxyCreator.shouldSkip()方法中的List<Advisor> candidateAdvisors = findCandidateAdvisors();返回找到的候選的加強器,而後再調用父類的shouldSkip()返回false,就是不跳過的意思

   執行完shouldSkip()返回到AbstractAutoProxyCreator.postProcessBeforeInstantiation的方法,至此postProcessBeforeInstantiation執行完成。

   最後AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了Bean的後置處理器BeanPostProcessor接口:

  該接口有2個方法:postProcessBeforeInitialization和postProcessAfterInitialization,其中在postProcessAfterInitialization方法主要就是經過前面建立的加強器來建立代理對象

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if (bean != null) {
            //獲取緩存key
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //若是有必要就代理
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

  進入若是必要就代理方法,wrapIfNecessary(bean, beanName, cacheKey):

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;
        }
        //是否是基礎的bean 是否是須要跳過的
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        //若是有匹配的通知,就建立代理對象
        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;
    }

  ① 獲取匹配的通知方法,getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null):

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();
    }

  跟進到找合適的加強器對象方法,findEligibleAdvisors(beanClass, beanName):

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //找到Spring IoC容器中全部的候選通知
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //判斷找到的通知能不能做用到當前的類上
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        //對咱們的advisor進行排序
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

  跟進到判斷找到的通知能不能做用到當前的類上方法,findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName):

protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            //從候選的通知器中找到合適正在建立的實例對象的通知器
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }

  跟進到從候選的通知器中找到合適正在建立的實例對象的通知器方法,AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass):

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        //若候選的加強器集合爲空 直接返回
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        //定義一個合適的加強器集合對象
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        //循環咱們候選的加強器對象
        for (Advisor candidate : candidateAdvisors) {
            //判斷咱們的加強器對象是否是實現了IntroductionAdvisor (很明顯咱們事務的沒有實現 因此不會走下面的邏輯)
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        //不爲空
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            //判斷咱們的加強器對象是否是實現了IntroductionAdvisor (很明顯咱們事務的沒有實現 因此不會走下面的邏輯)
            if (candidate instanceof IntroductionAdvisor) {
                //在上面已經處理過 ,不須要處理
                continue;
            }
            /**
             * 真正的判斷加強器是否合適當前類型
             */
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

  跟進到是否能用方法,canApply(candidate, clazz, hasIntroductions):

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        //判斷咱們的加強器是不是IntroductionAdvisor
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        //判斷咱們事務的加強器BeanFactoryTransactionAttributeSourceAdvisor是否實現了PointcutAdvisor
        else if (advisor instanceof PointcutAdvisor) {
            //轉爲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;
        }
    }

  跟進到找到真正能用的加強器方法,canApply(pca.getPointcut(), targetClass, hasIntroductions):

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 introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        //建立一個集合用於保存targetClass的class對象
        Set<Class<?>> classes = new LinkedHashSet<>();
        //判斷當前class是否是代理的class對象
        if (!Proxy.isProxyClass(targetClass)) {
            //加入到集合中去
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        //獲取到targetClass所實現的接口的class對象,而後加入到集合中
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        //循環全部的class對象
        for (Class<?> clazz : classes) {
            //經過class獲取到全部的方法
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            //循環咱們的方法
            for (Method method : methods) {
                //經過methodMatcher.matches來匹配咱們的方法
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        //經過方法匹配器進行匹配
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }
        return false;
    }

  若是該方法返回true就表示匹配,就添加到合適的集合eligibleAdvisors中,遍歷完全部的候選加強器後,debug截圖以下:

   返回到AbstractAdvisorAutoProxyCreator.findEligibleAdvisors方法中,而後擴展加強器,若是合適的加強器列表不是空的就排序。

   返回到AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean,若是空就表示不須要代理,不爲空就表示須要代理。

   ② 真正建立代理對象,Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)):

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);

        //爲proxyFactory設置建立jdk仍是cglib代理
        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        //把咱們的specificInterceptors數組中的Advisor轉化爲數組形式的
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        //爲咱們的代理工加入通知器,
        proxyFactory.addAdvisors(advisors);
        //設置targetSource對象
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        //真正建立代理對象
        return proxyFactory.getProxy(getProxyClassLoader());
    }

  跟進到真正建立代理對象方法,proxyFactory.getProxy(getProxyClassLoader()):

public Object getProxy(@Nullable ClassLoader classLoader) {
        //createAopProxy() 用來建立咱們的代理工廠
        return createAopProxy().getProxy(classLoader);
    }

  跟進到建立AOP代理方法,createAopProxy():

protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

  跟進到getAopProxyFactory().createAopProxy(this):

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        //判斷咱們是否指定使用cglib代理ProxyTargetClass =true  默認false
        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.");
            }
            //targetClass是接口使用的就是jdk代理
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            //cglib代理
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            //jdk動態代理
            return new JdkDynamicAopProxy(config);
        }
    }

  跟進到建立動態代理(注意這個是jdk的,cglib同理)方法,getProxy(classLoader):

public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        //建立jdk動態代理
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

  有沒有眼前一亮:該方法用來建立咱們的代理對象,若是proxyTargetClass = true,建立cglib代理 ,爲false,若是代理類沒有實現接口也建立cglib代理,不然建立jdk代理

  至此AnnotationAwareAspectJAutoProxyCreator建立動態代理完成!!

 4、AOP動態代理invoke

  以JdkDynamicAopProxy爲例,CGLIB動態代理參照Jdk動態代理自行分析

   JdkDynamicAopProxy的invole方法:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        //獲取到咱們的目標對象
        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            //如果equals方法不須要代理
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            //如果hashCode方法不須要代理
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            //如果DecoratingProxy也不要攔截器執行
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            /**
             * 這個配置是暴露咱們的代理對象到線程變量中,須要搭配@EnableAspectJAutoProxy(exposeProxy = true)一塊兒使用
        * 好比在目標對象方法中再次獲取代理對象可使用這個AopContext.currentProxy() * 還有的就是事務方法調用事務方法的時候也是用到這個
*/ if (this.advised.exposeProxy) { //把咱們的代理對象暴露到線程變量中 oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //獲取咱們的目標對象 target = targetSource.getTarget(); //獲取咱們目標對象的class Class<?> targetClass = (target != null ? target.getClass() : null); //把aop的advisor轉化爲攔截器鏈 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //若是攔截器鏈爲空 if (chain.isEmpty()) { //經過反射直接調用執行 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //建立一個方法調用對象 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //調用執行 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. 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()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }

  跟進到invocation.proceed()方法,該方法的調用用到了遞歸和責任鏈設計模式:

public Object proceed() throws Throwable {
        //從-1開始,下標=攔截器的長度-1的條件知足表示執行到了最後一個攔截器的時候,此時執行目標方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        //獲取第一個方法攔截器使用的是前++
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

  跟進到((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,責任鏈模式,執行順序以下:

  ① ExposeInvocationInterceptor.invoke方法:

public Object invoke(MethodInvocation mi) throws Throwable {
        MethodInvocation oldInvocation = invocation.get();
        invocation.set(mi);
        try {
            return mi.proceed();
        }
        finally {
            invocation.set(oldInvocation);
        }
    }

  ② AspectJAfterThrowingAdvice.invoke方法:

public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            //執行下一個通知/攔截器
            return mi.proceed();
        }
        catch (Throwable ex) {
            //拋出異常
            if (shouldInvokeOnThrowing(ex)) {
                //執行異常通知
                invokeAdviceMethod(getJoinPointMatch(), null, ex);
            }
            throw ex;
        }
    }

  ③ AfterReturningAdviceInterceptor.invoke方法:

public Object invoke(MethodInvocation mi) throws Throwable {
        //執行下一個通知/攔截器
        Object retVal = mi.proceed();
        //返回通知方法
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }

  ④ AspectJAfterAdvice.invoke方法:

public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            //執行下一個通知/攔截器
            return mi.proceed();
        }
        finally {
            //後置通知的方法老是會被執行 緣由就在這finally
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }

  ⑤ AspectJAroundAdvice.invoke方法:

public Object invoke(MethodInvocation mi) throws Throwable {
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        }
        ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
        ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
        JoinPointMatch jpm = getJoinPointMatch(pmi);
        return invokeAdviceMethod(pjp, jpm, null, null);
    }

  ⑥ MethodBeforeAdviceInterceptor.invoke方法:

public Object invoke(MethodInvocation mi) throws Throwable {
        //執行前置通知的方法
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        //執行下一個通知/攔截器,可是該攔截器是最後一個了,因此會調用目標方法
        return mi.proceed();
    }

  運行的執行順序以下:

   JdkDynamicAopProxy的invole方法流程圖以下:

  注意:該流程圖是以本人的spring系列中的spring-aop模塊中的LogAspect爲例的。

  總結:經過@EnableAspectJAutoProxy註解開啓AOP功能,該註解爲咱們Spring容器中註冊了AnnotationAwareAspectJAuto ProxyCreator組件,AOP的準備和代理建立都在這個組件中完成,AnnotationAwareAspectJAutoProxyCreator繼承AbstractAuto ProxyCreator實現了InstantiationAwareBeanPostProcessor接口,在方法postProcessBeforeInstantiation中找到Spring容器中全部的加強器,爲建立代理作準備;AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了BeanPost Processor接口,在方法postProcessAfterInitialization中經過前面找到的候選加強器中找到合適的加強器來建立代理對象,最後調用目標方法,進去到代理對象的invoke方法中進行調用。

相關文章
相關標籤/搜索