Spring中@Transactional注解到底做了什么(二)------@Transactional解析入口

這一章我們來(lái)看看事務(wù)的具體參數(shù)在項(xiàng)目啟動(dòng)后,是在哪個(gè)入口加載和解析的

入口

TxNamespaceHandler類,TxNamespaceHandler類是spring-tx包的自定義解析器,在它的init方法中,有一個(gè)AnnotationDrivenBeanDefinitionParser類,

    @Override
    public void init() {
        registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
        //<tx:annotation-driven開(kāi)頭的配置聂使, Spring會(huì)使用AnnotationDrivenBeanDefinitionParser類的 parse方法進(jìn)行解析
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
    }

再看AnnotationDrivenBeanDefinitionParser類中的parse方法

    @Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        registerTransactionalEventListenerFactory(parserContext);
        String mode = element.getAttribute("mode");
        if ("aspectj".equals(mode)) {
            //類型為"aspectj"
            registerTransactionAspect(element, parserContext);
            if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
                registerJtaTransactionAspect(element, parserContext);
            }
        }
        else {
            //類型為"proxy" 默認(rèn)
            AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
        }
        return null;
    }
private static class AopAutoProxyConfigurer {

        public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
            AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

            String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
            if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
                Object eleSource = parserContext.extractSource(element);

                // Create the TransactionAttributeSource definition.
                //創(chuàng)建TransactionAttributeSource的bean
                RootBeanDefinition sourceDef = new RootBeanDefinition(
                        "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
                sourceDef.setSource(eleSource);
                sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

                // Create the TransactionInterceptor definition.
                //創(chuàng)建TransactionInterceptor的bean 后面使用TransactionInterceptor作為事務(wù)增強(qiáng)器實(shí)現(xiàn)事務(wù)的邏輯
                RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
                interceptorDef.setSource(eleSource);
                interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                registerTransactionManager(element, interceptorDef);
                interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
                String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

                // Create the TransactionAttributeSourceAdvisor definition.
                //創(chuàng)建TransactionAttributeSourceAdvisor的bean
                RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
                advisorDef.setSource(eleSource);
                advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
                advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
                if (element.hasAttribute("order")) {
                    advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
                }
                parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

                CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
                compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
                compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
                compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
                parserContext.registerComponent(compositeDef);
            }
        }
    }

一步步往下走,在configureAutoProxyCreator方法中我們目前只關(guān)注registerAutoProxyCreatorIfNecessary方法

    public static void registerAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {

        BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

然后在AopConfigUtils.registerAutoProxyCreatorIfNecessary方法中

    @Nullable
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
    }

那么在registerAutoProxyCreatorIfNecessary方法中辆苔,我們能看到的是注冊(cè)了一個(gè)InfrastructureAdvisorAutoProxyCreator類型的bean而已菲驴,那么屬于事務(wù)關(guān)鍵流程的又是哪一步呢?
其實(shí)上面這一串代碼流程走下來(lái),主要往正常的bean注冊(cè)的流程靠近,InfrastructureAdvisorAutoProxyCreator類繼承了AbstractAdvisorAutoProxyCreator類,而AbstractAdvisorAutoProxyCreator類又繼承了AbstractAutoProxyCreator類统诺,而AbstractAutoProxyCreator類就是bean實(shí)例化的重要類,其中的postProcessAfterInitialization方法才是接下來(lái)流程的關(guān)鍵

   @Override
   public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
       if (bean != null) {
           // 根據(jù)給定的 bean的class和name 構(gòu)建一個(gè) key
           Object cacheKey = getCacheKey(bean.getClass(), beanName);
           if (this.earlyProxyReferences.remove(cacheKey) != bean) {
               // 如果它適合被代理 則要封裝指定 bean
               return wrapIfNecessary(bean, beanName, cacheKey);
           }
       }
       return bean;
   }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挺物,一起剝皮案震驚了整個(gè)濱河市次伶,隨后出現(xiàn)的幾起案子赶撰,更是在濱河造成了極大的恐慌,老刑警劉巖骂澄,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡紊遵,警方通過(guò)查閱死者的電腦和手機(jī)学搜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門钉凌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)御雕,“玉大人,你說(shuō)我怎么就攤上這事滥搭∩遥” “怎么了闽坡?”我有些...
    開(kāi)封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵论悴,是天一觀的道長(zhǎng)帕棉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)饼记,這世上最難降的妖魔是什么香伴? 我笑而不...
    開(kāi)封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任捺僻,我火速辦了婚禮乡洼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匕坯。我一直安慰自己束昵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布葛峻。 她就那樣靜靜地躺著锹雏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪术奖。 梳的紋絲不亂的頭發(fā)上礁遵,一...
    開(kāi)封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音采记,去河邊找鬼佣耐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唧龄,可吹牛的內(nèi)容都是我干的兼砖。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼讽挟!你這毒婦竟也來(lái)了懒叛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤耽梅,失蹤者是張志新(化名)和其女友劉穎薛窥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體褐墅,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拆檬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妥凳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竟贯。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖逝钥,靈堂內(nèi)的尸體忽然破棺而出屑那,到底是詐尸還是另有隱情,我是刑警寧澤艘款,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布持际,位于F島的核電站,受9級(jí)特大地震影響哗咆,放射性物質(zhì)發(fā)生泄漏蜘欲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一晌柬、第九天 我趴在偏房一處隱蔽的房頂上張望姥份。 院中可真熱鬧,春花似錦年碘、人聲如沸澈歉。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)埃难。三九已至,卻和暖如春涤久,著一層夾襖步出監(jiān)牢的瞬間涡尘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工响迂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悟衩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓栓拜,卻偏偏與公主長(zhǎng)得像座泳,于是被迫代替她去往敵國(guó)和親惠昔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 1.Spring整體架構(gòu) 1)核心容器(Core Container) Core模塊挑势,主要包含了Spring框架基...
    Sponge1128閱讀 1,057評(píng)論 0 1
  • 這部分主要是開(kāi)源Java EE框架方面的內(nèi)容镇防,包括Hibernate、MyBatis潮饱、Spring来氧、Spring ...
    雜貨鋪老板閱讀 1,357評(píng)論 0 2
  • 作者: 一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-12-29】 更新日志 日期更新內(nèi)容備注2017-12-29創(chuàng)建分析文檔...
    一字馬胡閱讀 12,078評(píng)論 2 32
  • spring源碼分析(二) 目錄五、Spring 源碼解讀--5.1香拉、什么是IOC/DI--5.2啦扬、Spring ...
    毛子果閱讀 398評(píng)論 0 0
  • XML解析的準(zhǔn)備工作 使用ResourceLoader將資源文件路徑轉(zhuǎn)換為Resource文件。封裝資源文件凫碌。使用...
    一生逍遙一生閱讀 2,255評(píng)論 0 1