Spring系列之Spring框架和SpringAOP集成過程分析(十一)

轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80725173
我們在這篇文章中來分析一下AnnotationAwareAspectJAutoProxyCreator這個類,看這個類的名字我們大概可以知道它主要是爲AspectJ註解提供服務的類。這個類不得了了是一個相當厲害的類,在這個類中可以識別應用中的所有切面類,爲目標類找尋合適的Advisor,將目標類變爲代理類等功能。話不多說了,下面我們來簡單的分析一下這個類。
首先我們來看一下這個類的類圖:
AnnotationAwareAspectJAutoProxyCreator
從上面的圖中我們可以看到AnnotationAwareAspectJAutoProxyCreator這個類間接實現了BeanFactoryAware、BeanClassLoaderAware、Ordered、BeanPostProcessor接口。如果之前沒有了解過Spring Bean的生命週期(或者是Spring開放的對Bean進行修改的擴展接口)的話,請點擊這裏查看(Spring Bean的生命週期小析(一)Spring Bean的生命週期小析(二))這裏就不再多說了。上面提到的接口的實現類大多是在AbstractAutoProxyCreator這個類中實現的。Spring提供的這些關於Bean的擴展接口大大方便了我們在Bean的創建過程中對Bean進行一些修改的操作。我們按照順序來看看AnnotationAwareAspectJAutoProxyCreator這個關係鏈上對這些接口的實現。

AbstractAdvisorAutoProxyCreator#setBeanFactory

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        //掉用父類的setBeanFactory 這裏只是一個簡單的賦值
        super.setBeanFactory(beanFactory);
        //如果BeanFactory不是ConfigurableListableBeanFactory類型的 拋出異常
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException(
                    "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        //初始化BeanFactory
        initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    }
    //這個方法在AnnotationAwareAspectJAutoProxyCreator這個類型中
    @Override
    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //調用父類的initBeanFactory 執行的內容如下:
        //this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
        //創建BeanFactoryAdvisorRetrievalHelperAdapter 從BeanFactory中獲取Advisor類型的Bean
        super.initBeanFactory(beanFactory);
        if (this.aspectJAdvisorFactory == null) {
            //創建ReflectiveAspectJAdvisorFactory 相當重要的一個類
            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
        }
        //創建BeanFactoryAspectJAdvisorsBuilderAdapter 相當重要的一個類
        //爲目標類型創建對應的Advisor的類
        this.aspectJAdvisorsBuilder =
                new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    }

AbstractAutoProxyCreator#postProcessBeforeInstantiation

這個方法可以讓我們在Bean被Spring容器實例化之前提前創建Bean,如果這個方法返回的值不是null,那就中斷其他類對這個接口的實現,直接返回這個創建的Bean。在AbstractAutoProxyCreator中其源碼如下:

    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        //得到一個緩存的key 實現是:如果是beanClass是FactoryBean類型,則在beanName前面加&
        Object cacheKey = getCacheKey(beanClass, beanName);
        //如果目標Bean的集合中包這個beanName的話 則跳過
        if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            //isInfrastructureClass 判斷是不是負責AOP基礎建設的Bean,如果是AOP基礎建設的Bean不能在這裏被創建代理對象
            //那麼什麼樣的Bean是AOP的基礎建設Bean呢?Advice、Pointcut、Advisor、AopInfrastructureBean類型的Bean
            //以及含有Aspect註解的Bean
            //shouldSkip這個方法是判斷這個類型的Bean能不能被跳過,如果可以跳過,那麼就不提前創建這個類
            //這個類我們在下面詳細分析
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                //緩存這個beanClass
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }
        / 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.
        if (beanName != null) {
            //一般我們都是不配置TargetSourceCreator 下面的步驟我們先跳過 在後面我們還會繼續分析下面的內容的
            TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
            if (targetSource != null) {
                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;
            }
        }

AspectJAwareAdvisorAutoProxyCreator#shouldSkip

    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
        // TODO: Consider optimization by caching the list of the aspect names
        //我們重點看到是findCandidateAdvisors這個方法的內容
        //查找所有可選擇對的Advisor 並且或進行緩存
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        for (Advisor advisor : candidateAdvisors) {
            if (advisor instanceof AspectJPointcutAdvisor) {
                //如果AbstractAspectJAdvice類型的Advice中有aspectName和beanName相等則跳過
                if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                    return true;
                }
            }
        }
        //父類直接返回一個false
        return super.shouldSkip(beanClass, beanName);
    }
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        // 同樣是先調用父類的findCandidateAdvisors
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        //構建所有切面Bean中的Advisor
        //很重要的一個方法 下面分析
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }
    // AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
    protected List<Advisor> findCandidateAdvisors() {
        //這個advisorRetrievalHelper 就是我們在 initBeanFactory中創建的BeanFactoryAdvisorRetrievalHelper
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

    // BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
    //這個方法的內容是從Spring容器中獲取Advisor類型的Bean
    public List<Advisor> findAdvisorBeans() {
        // Determine list of advisor bean names, if not cached already.
        String[] advisorNames = null;
        synchronized (this) {
            //先看看之前是不是緩存過
            advisorNames = this.cachedAdvisorBeanNames;
            if (advisorNames == null) {
                // Do not initialize FactoryBeans here: We need to leave all regular beans
                // uninitialized to let the auto-proxy creator apply to them!
                //上面的註釋說的很清楚 這裏不會初始化FactoryBean 爲什麼會這樣說呢?因爲提前導致FactoryBean類型的Bean被創建的話是會有問題的
                //從BeanFactory中獲取所有的Advisor類型的Bean
                advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Advisor.class, true, false);
                //這裏進行賦值緩存
                this.cachedAdvisorBeanNames = advisorNames;
            }
        }
        //如果沒有Advisor類型的Bean的話 直接返回
        //如果你有特殊需求的話 可以實現Advisor接口,並向Spring容器中注入對應的Bean
        if (advisorNames.length == 0) {
            return new LinkedList<Advisor>();
        }
        //這裏是默認創建了一個 Advisor類型的集合 
        List<Advisor> advisors = new LinkedList<Advisor>();
        for (String name : advisorNames) {
            //這裏默認返回的是true
            if (isEligibleBean(name)) {
                //如果是正在創建中的Bean 則跳過
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Skipping currently created advisor '" + name + "'");
                    }
                }
                else {
                    try {
                        //從BeanFactory中獲取對應的Bean 這裏如果Bean還沒創建 會導致Bean創建
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    }
                    catch (BeanCreationException ex) {
                    //異常處理 略
                    }
                }
            }
        }
        return advisors;
    }

下面我們來看看BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors中的這個方法,從名字我們就可以看出來這是一個從BeanFactory中構建Advisor的方法。

    public List<Advisor> buildAspectJAdvisors() {
        //所有的切面的名字 這裏的處理邏輯和上面的是一樣的 獲取到所有的切面BeanName之後緩存起來 volatile類型的
        List<String> aspectNames = this.aspectBeanNames;
        if (aspectNames == null) {
            synchronized (this) {
                //這裏又賦值了一次  看着這個邏輯是不是和某個單例的寫法很像啊?
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    List<Advisor> advisors = new LinkedList<Advisor>();
                    aspectNames = new LinkedList<String>();
                    //這裏是從BeanFactory中獲取所有的Bean
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    for (String beanName : beanNames) {
                        //這裏默認都是true
                        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.
                        //注意看上面這個註釋的內容:在這個場景下我們獲取BeanClass的時候必須要小心處理,以免會提前初始化
                        //Bean,這些Bean在初始化之後會被Spring容器緩存起來,但是這些Bean可能還沒有被織入。
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        //判斷上面獲取到的BeanClass是否帶有Aspect註解
                        if (this.advisorFactory.isAspect(beanType)) {
                            //添加到 aspectNames中
                            aspectNames.add(beanName);
                            //創建切面元數據 這部門的內容和我們之前分析大致差不多 我們就不再詳細分析了
                            //請看這裏: https://blog.csdn.net/zknxx/article/details/79685290
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                //注意這裏放入了 BeanFactory的引用 方便後面從BeanFactory中獲取切面的實例
                                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");
                                }
                                //這裏使用的是 PrototypeAspectInstanceFactory
                                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();
        }
        //下面這些就是從緩存中獲取Advisor了
        List<Advisor> advisors = new LinkedList<Advisor>();
        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;
    }

總結起來findCandidateAdvisors這個方法的內容就是從Spring容器中獲取所有Advisor類型的Bean和切面中所有帶有通知註解的方法並將其封裝爲Advisor。那麼其實我們在AbstractAutoProxyCreator的postProcessBeforeInstantiation方法中就獲取到了Spring容器中的所有Advisor。

AbstractAutoProxyCreator#postProcessAfterInstantiation
    //通常都是返回true
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) {
        return true;
    }

AbstractAutoProxyCreator#postProcessPropertyValues

    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
        //不做處理
        return pvs;
    }

AbstractAutoProxyCreator#postProcessBeforeInitialization

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        //不做處理原樣返回
        return bean;
    }
AbstractAutoProxyCreator#postProcessAfterInitialization

這個方法需要重點分析一下了

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
          if (bean != null) {
            //獲取緩存的key
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            //如果不是提前引用的Bean
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                //如果需要的話 對傳入的Bean進行包裝
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
    //這個方法的主要作用就是創建代理對象
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //如果已經創建過了 
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        //如果這裏返回的是False的話 直接返回
        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;
        }
        //getAdvicesAndAdvisorsForBean這個方法下面我們要重點說一下
        // 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;
        }
        //如果不需要創建代理對象的話  這裏緩存false
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80725173

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章