1. 程式人生 > >Spring事務切面原理

Spring事務切面原理

一、前言

本節我們來談談 <tx:advice/>、<aop:config> 標籤如何建立事務切面的。

二、<tx:advice/>、<aop:config> 標籤如何建立事務切面的

<tx:advice/>標籤作用是建立一個TransactionInterceptor,作為事務切面的通知方法。在Spring中(可以參考:https://gitbook.cn/gitchat/activity/5a8fdf6bf2e5dc2ca621a937) Advisor這個概念是從 Spring 1.2的 AOP 支援中提出的,一個 Advisor 相當於一個小型的切面,不同的是它只有一個通知(Advice),Advisor中還包含一個pointcut(切點),切點定義了對那些方法進行攔截,而通知是具體對攔截到的方法進行增強的邏輯。

具體對<tx:advice/>標籤進行解析的是TxAdviceBeanDefinitionParser,其時序圖如下:
enter image description here

首先TxAdviceBeanDefinitionParser有getBeanClass方法程式碼程式碼:

    protected Class<?> getBeanClass(Element element) {
        return TransactionInterceptor.class;
    }

這說明該標籤解析後生成的是TransactionInterceptor物件的bean定義。

  • 其中時序圖中步驟(2)是設定配置demo的XML配置檔案裡面建立的事務管理器到TransactionInterceptor物件,
    image.png

  • 時序圖(4)~(10)則解析<tx:advice/>標籤中事務屬性值設定到TransactionInterceptor物件裡面屬性裡面。

注:也就是<tx:advice/>標籤的作用是生成一個TransactionInterceptor攔擊器物件,並設定該物件的一些事務屬性,然後該物件將作為事務切面的通知方法。

<aop:config>標籤作用是建立一個DefaultBeanFactoryPointcutAdvisor(其實現了Advisor介面)物件作為作一個Advisor,前面說了一個Advisor就是一個小型的切面,所以其中定義了切點和通知。該標籤是ConfigBeanDefinitionParser類進行解析的,其時序圖如下:
enter image description here

  • 時序圖中步驟(2)建立了一個DefaultBeanFactoryPointcutAdvisor物件的bean定義,步驟(3)(4)則是設定上面建立的通知物件(TransactionInterceptor)到該Advisor

  • 時序圖中步驟(8)則是解析標籤中的切點表示式,然後設定到DefaultBeanFactoryPointcutAdvisor物件的bean定義。

  • 時序圖步驟(4)註冊了一個AspectJAwareAdvisorAutoProxyCreator到Spring容器,作用就是對滿足pointcut表示式的類的方法進行代理,並且使用advice進行攔截處理,而advice就是事務攔截器。

由於AspectJAwareAdvisorAutoProxyCreator類實現了BeanPostProcessor介面,所以具有postProcessAfterInitialization方法,而對符合切點的方法進行代理就是在該方法內的wrapIfNecessary方法:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        ...
        // 8.1
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //8.2
            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;
    }

其中8.1查詢所有可以對當前bean進行增強的切面,其中有一個條件就是看那些bean實現了Advisor介面,而<aop:config>標籤作用是建立一個DefaultBeanFactoryPointcutAdvisor,並且其實現了Advisor介面,所以這裡會使用DefaultBeanFactoryPointcutAdvisor切面,然後會看當前bean的方法是否滿足切面的切點表示式,具體是AopUtils的canApply方法進行判斷:
image.png

如果滿足則執行8.2對方法進行代理,這裡會對TestTransactionProgagationUserImpl、TestTransactionProgagationCourseImpl、UserManagerBoImpl類的所有方法進行事務代理。

注:Spring框架中一個 Advisor 相當於一個小型的切面,<tx:advice/>定義了這個切面的通知方法,而<aop:config>具體定義了一個Advisor切面,並且內部定義了一個切點,並且引入了<tx:advice/>定義的通知方法

最後

想了解更多關於粘包半包問題單擊我
更多關於分散式系統中服務降級策略的知識可以單擊 單擊我
想系統學dubbo的單擊我
想學併發的童鞋可以 單擊我