權(quán)限、事務(wù)、日志處理如果混雜在業(yè)務(wù)代碼之中會(huì)使整個(gè)代碼變得非常復(fù)雜而且可讀性很差,難以修改重構(gòu)。

          面向?qū)ο蟮姆治龊驮O(shè)計(jì)引入了繼承、抽象和多態(tài)等概念,由此為我們提供了降低軟件復(fù)雜性的工具。但是,開(kāi)發(fā)人員在軟件設(shè)計(jì)過(guò)程中仍然經(jīng)常會(huì)面對(duì)無(wú)法用面向?qū)ο筌浖_(kāi)發(fā)技術(shù)輕易解決的問(wèn)題。這些問(wèn)題之一就是如何處理應(yīng)用程序中的橫切關(guān)注點(diǎn)(Cross-cutting concerns)。

          1、橫切關(guān)注點(diǎn)

          關(guān)注點(diǎn)就是設(shè)計(jì)人員感興趣的某一概念或區(qū)域。例如,在一個(gè)訂貨系統(tǒng)中,核心關(guān)注點(diǎn)可能是訂單處理和生產(chǎn),而系統(tǒng)關(guān)注點(diǎn)可能是事務(wù)處理和安全管理。

          橫切關(guān)注點(diǎn)是影響多個(gè)類(lèi)或模塊的關(guān)注點(diǎn),即未能很好地局部化和模塊化的關(guān)注點(diǎn)。

          橫切關(guān)注點(diǎn)的表現(xiàn)有:

          ·代碼糾結(jié)當(dāng)一個(gè)模塊或代碼段同時(shí)管理多個(gè)關(guān)注點(diǎn)時(shí)發(fā)生這種情況。

          ·代碼分散當(dāng)一個(gè)關(guān)注點(diǎn)分布在許多模塊中并且未能很好地局部化和模塊化時(shí)發(fā)生這種情況。

          這些現(xiàn)象會(huì)從幾個(gè)方面影響軟件;例如,它們會(huì)導(dǎo)致軟件難以維護(hù)和重用,并且難以編寫(xiě)和理解。

          2、關(guān)注點(diǎn)的隔離

          面向方面編程試圖通過(guò)引入關(guān)注點(diǎn)的隔離這一概念來(lái)解決這些問(wèn)題。采用這一概念,可以以一種模塊化而且適當(dāng)局部化的方式實(shí)現(xiàn)關(guān)注點(diǎn)。AOP解決這個(gè)問(wèn)題的辦法是在設(shè)計(jì)空間中增加額外一維,并且引入了一些構(gòu)造,這些構(gòu)造使我們能夠定義橫切關(guān)注點(diǎn),將它們轉(zhuǎn)移進(jìn)新的維,并且以模塊化方式將它們打 包。

          聲明式的AOP事務(wù)配置如下:

          <bean id="nodeTarget"

                        class="com.daosheng.service.impl.NodeManagerImpl" singleton="true"

                        lazy-init="default" autowire="default" dependency-check="default">

                        <property name="dao">

                               <ref local="nodeDAO" />

                        </property>         

                 </bean>

                 <bean id="nodeManager"

                        class="com.daosheng.cms.right.RightTransactionProxyFactoryBean"

                        singleton="true" lazy-init="default" autowire="default"

                        dependency-check="default">

                        <property name="transactionManager">

                               <ref local="transactionManager" />

                        </property>

                        <property name="target">

                               <ref local="nodeTarget" />

                        </property>

                        <property name="transactionAttributes">

                               <props>                     

                                      <prop key="insert*">

                                             PROPAGATION_REQUIRED,-ApplicationException

                                      </prop>

                                      <prop key="update*">

                                             PROPAGATION_REQUIRED,-ApplicationException

                                      </prop>

                               </props>

                        </property>

                 </bean>

           

          其實(shí)在注冊(cè)nodeManager時(shí)注冊(cè)的實(shí)際類(lèi)不是自己開(kāi)發(fā)的NodeManagerImpl類(lèi)而是注冊(cè)的RightTransactionProxyFactoryBean代理工廠(chǎng)類(lèi)。在其它類(lèi)里調(diào)用的nodeManager方法實(shí)際上是先調(diào)用的此代理工廠(chǎng)類(lèi)的加入橫切點(diǎn)代碼(事務(wù)處理代碼)然后在調(diào)用的NodeManagerImpl的相應(yīng)方法,這樣就實(shí)現(xiàn)了NodeManagerImpl類(lèi)里不用操心事務(wù)問(wèn)題,而實(shí)際的事務(wù)由加入在切點(diǎn)的Advice來(lái)完成。其在真正方法執(zhí)行前啟動(dòng)事務(wù),執(zhí)行后提交事務(wù)(commit),如果出現(xiàn)異常則回滾(rollback)。

                 代理工廠(chǎng)類(lèi)是采用jdk4以上自帶的動(dòng)態(tài)代理機(jī)制實(shí)現(xiàn)的。

          框架的AOP中提供了4種處理切入類(lèi)型:around,before,after,introduction.顧名思義,  
          1) around
          是針對(duì)具體的某個(gè)切入點(diǎn)的方法(比如,現(xiàn)在有個(gè)OrderBook方法,around的切入類(lèi)型是就這個(gè)方法的內(nèi)部調(diào)用,是通過(guò)java的元 數(shù)據(jù),在運(yùn)行時(shí)通過(guò)Method.invoke來(lái)調(diào)用,具有返回值,當(dāng)發(fā)生意外的時(shí)候會(huì)終止.記住的一點(diǎn)是,返回值.);  
          2)before
          是在方法調(diào)用前調(diào)用(OrderBook方法前調(diào)用,但是沒(méi)有返回值,同時(shí)在通常意外情況下,會(huì)繼續(xù)運(yùn)行下一步方法.記住的一點(diǎn)是沒(méi)有返回值);  
          3)after
          before剛好相反,沒(méi)有什么特別的地方.  
          4)introduction
          是一個(gè)更加特殊的,但功能更加強(qiáng)大的切入類(lèi)型.比如(你現(xiàn)在有Book對(duì)象,Computer對(duì)象,還有幾十個(gè)這種業(yè)務(wù)對(duì)象,現(xiàn)在你希望在每個(gè)這樣的對(duì)象中都加入一個(gè)記錄最后修改的時(shí)間.但是你又不希望對(duì)每個(gè)類(lèi)都進(jìn)行修改,因?yàn)樘闊┝?/span>,同時(shí)更重要的一點(diǎn),破壞了對(duì)象的完整性,說(shuō)不定你以后又不需要這個(gè)時(shí)間數(shù)據(jù)了呢.框架AOP為了專(zhuān)門(mén)實(shí)現(xiàn)這種思想提供了一個(gè)切入處理,那就是introduction.introduction可以為動(dòng)態(tài)加入某些方法,這樣可以在運(yùn)行時(shí),強(qiáng)制轉(zhuǎn)換這些對(duì)象,進(jìn)行插入時(shí)間數(shù)據(jù)的動(dòng)作,更深的內(nèi)幕就是C++虛函數(shù)中的vtable思想).

          下面時(shí)序圖為事務(wù)在整個(gè)各層代碼協(xié)作過(guò)程中啟動(dòng)和提交的過(guò)程。每個(gè)Manager或者DAO實(shí)體可能是開(kāi)發(fā)的實(shí)際類(lèi)也可以是代理類(lèi)。

          TransactionAOP.bmp

          posts - 9, comments - 27, trackbacks - 0, articles - 19

          Copyright © publisher luo

          主站蜘蛛池模板: 河间市| 乌拉特后旗| 梅河口市| 凤翔县| 苍溪县| 眉山市| 云南省| 三亚市| 都江堰市| 岑溪市| 大邑县| 抚远县| 宜兴市| 华宁县| 镶黄旗| 马龙县| 高雄市| 讷河市| 高州市| 英吉沙县| 东至县| 平昌县| 卓资县| 胶州市| 龙山县| 东莞市| 青河县| 西贡区| 沧源| 白朗县| 遂溪县| 宜都市| 孟津县| 信宜市| 安吉县| 清涧县| 错那县| 兰西县| 玉田县| 萍乡市| 哈密市|