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

轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80724180
在開始這個系列之前大家先想一下我們是怎麼在項目中使用SpringAOP的(這裏的分析都是基於AspectJ註解的)。我們需要在我們的Spring配置文件中引入SpringAOP的命名空間和標籤,然後定義切面Bean,進行AOP配置。大概如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       <!--AOP的命名空間-->
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--開啓自動包掃描-->
    <context:component-scan base-package="com.zkn.spring.learn.aop.spring"/>
    <!--使用AspectJ註解-->
    <aop:aspectj-autoproxy/>
</beans>

我們在使用Spring中不同的功能的時候可能會引入不同的命名空間比如xmlns:context,xmlns:aop,xmlns:tx等等。關於命名空間的東西我們這裏先不多說。在Spring中定義了一個這樣的抽象類專門用來解析不同的命名空間。這個類是NamespaceHandler,我們看一下這個和這個類相關的一些子類:
NamespaceHandler
在不同的命名空間實現類中定義了不同類型的實現類,這些實現類主要是用來初始化一些解析對應的標籤的類。比如我們接下來要分析的AopNamespaceHandler這個類。在上面關於AOP的配置中,我們使用了一個AOP的標籤:

<aop:aspectj-autoproxy/>

爲什麼我們只要使用這個標籤,就可以使用SpringAOP的功能呢?看一下AopNamespaceHandler這個類的內容你就會明白了:

public class AopNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        // In 2.0 XSD as well as in 2.1 XSD.
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        //我們看到了這樣的一段代碼  aspectj-autoproxy這個再加上aop 是不是就是 aop:aspectj-autoproxy呢
        //這段代碼的意思是使用AspectJAutoProxyBeanDefinitionParser來解析aop:aspectj-autoproxy標籤
        //AspectJAutoProxyBeanDefinitionParser這個類就是SpringAOP和Spring框架結合的關鍵
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace as of 2.1
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}

PS:每個框架對應的NamespaceHandler就是你分析Spring中的對應框架的關鍵入口。
下面我們來分析一下AspectJAutoProxyBeanDefinitionParser這個類。先看一下它的parse方法。

    public BeanDefinition parse(Element element, ParserContext parserContext) {
        //這個地方是向ApplicationContext中注入使用AspectJ註解自動創建代理對象的bean
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        extendBeanDefinition(element, parserContext);
        return null;
    }

AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary的方法內容如下:

    public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {
        //parserContext.getRegistry()這個是獲取到的全局的BeanDefinitionRegistry
        //我們看這個方法做了什麼
        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        //這兩個方法的內容一看就知道是什麼意思了 就先不分析了
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source)   {
        //這裏傳入了一個AnnotationAwareAspectJAutoProxyCreator的class
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        //這裏先判斷是不是已經注入過name爲org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition了
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            //如果已經注入過了 判斷之前注入的BeanDefinition的Class和傳入的Class是不是一致
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                //如果不一致的話 則取他們的優先級
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                //優先級高的生效 這個優先級 一會兒說
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            return null;
        }
        //如果之前沒有向BeanDefinitionRegistry中注入過此beanname的BeanDefinition
        //那就創建一個新的BeanDefinition添加到BeanDefinitionRegistry中
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

我們上面提到了一個優先級的東西,那這個優先級是在哪兒定義的呢?在AopConfigUtils中有這樣的一段代碼:

    static {
        APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
    }

在AopConfigUtils初始化的時候就會向APC_PRIORITY_LIST中添加這三個Class類。而上面提到的優先級就是他們在APC_PRIORITY_LIST中的位置。由此可見AspectJAwareAdvisorAutoProxyCreator會覆蓋InfrastructureAdvisorAutoProxyCreatorBeanDefinition中的class,而AnnotationAwareAspectJAutoProxyCreator又會覆蓋AspectJAwareAdvisorAutoProxyCreator的BeanDefinition中的class(當然也會覆蓋InfrastructureAdvisorAutoProxyCreator的BeanDefinition)。而我們在上面傳入的Class是AnnotationAwareAspectJAutoProxyCreator,即是優先級最大的Class。說了半天,這三個Class都有什麼用呢?和我們今天說的SpringAOP又有什麼關係呢?通過上面的分析,我們只知道使用

<aop:aspectj-autoproxy/>

會向BeanDefinitionRegistry中注入一個beanClass爲AnnotationAwareAspectJAutoProxyCreator的Bean。
我們先來看一下這三個類的關係:
AbstractAdvisorAutoProxyCreator
我們發現他們三個是同一個類的子類:AbstractAdvisorAutoProxyCreator,這個類的作用是創建代理對象併爲每個代理對象找到合適的Advisor(這一部分的東西可以參考前面的博文),那麼它的子類也具有相同的功能。AnnotationAwareAspectJAutoProxyCreator主要是爲AspectJ註解服務的,InfrastructureAdvisorAutoProxyCreator是一個基礎建設性的類,即識別不使用AspectJ註解的AOP配置(比如事務的實現)。OK,我們在上廢話了一大堆其實就是說了一件事:那就是在Spring啓動的時候會使用AopNamespaceHandler和AspectJAutoProxyBeanDefinitionParser來解析AOP標籤,並注入對應的BeanDefinition(AnnotationAwareAspectJAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator)。
我們在項目中使用AspectJ註解比較多,所以我們在下篇文章中會分析一下AnnotationAwareAspectJAutoProxyCreator這個類。
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80724180

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