Sung in Blog

                     一些技術(shù)文章 & 一些生活雜碎
          事務(wù)管理
          抽象出一個(gè)數(shù)據(jù)訪問的API是不夠的;我們還需要考慮事務(wù)管理。JTA是顯而易見的選擇,但是它是一個(gè)直接用起來很笨重的API,因而許多J2EE開發(fā)者感到EJB CMT是對(duì)于事務(wù)管理唯一合理的選擇。

          Spring提供了它自己對(duì)事務(wù)管理的抽象。Spring提供了這些:


            通過類似于JdbcTemplate的回調(diào)模板編程管理事務(wù),比起直接使用JTA要容易多了

            類似于EJB CMT的聲明式事務(wù)管理,但是不需要EJB容器

          Spring的事務(wù)抽象式唯一的,它不綁定到JTA或者任何其他事務(wù)管理技術(shù)。Spring使用事務(wù)策略的概念把程序代碼和底層的事務(wù)架構(gòu)(例如JDBC)解藕。

          為什么你要關(guān)心這些?JTA不是所有事務(wù)管理的最好答案嗎?如果你正在編寫僅僅使用一個(gè)數(shù)據(jù)庫(kù)的程序,你不需要JTA的復(fù)雜度。你不關(guān)心XA事務(wù)或者兩階段提交。你甚至不需要提供這些東西的高端應(yīng)用服務(wù)器。但是另一方面,你不會(huì)希望在需要和多個(gè)數(shù)據(jù)源打交道的時(shí)候重寫你的代碼。

          假定你決定通過直接使用JDBC或者Hibernate的事務(wù)以避免JTA帶來的額外負(fù)擔(dān)。一旦你需要處理多個(gè)數(shù)據(jù)源,你必須剝開所有的事務(wù)管理代碼并且使用JTA事務(wù)來替代。這不是非常有吸引力的并且導(dǎo)致大部分J2EE程序員,包括我自己,推薦只使用全局JTA事務(wù)。然而使用Spring事務(wù)抽象,你只需要重新配置Spring讓它使用JTA,而不是JDBC或者Hibernate的事務(wù)策略,就一切OK了。這是一個(gè)配置上的改變,而不是代碼的改動(dòng)。因而,Spring使得你能夠自由縮放應(yīng)用。


          AOP

          最近在應(yīng)用AOP來解決企業(yè)關(guān)注點(diǎn)方面大家有了很大的興趣,例如事務(wù)管理,這些都是EJB所要解決的。

          Spring的AOP支持的首要目標(biāo)是要給POJOs提供J2EE服務(wù)。這類似于JBoss 4的目標(biāo),Spring AOP由它能夠在應(yīng)用服務(wù)器之間移植的優(yōu)勢(shì),因而沒有綁死在廠商身上的風(fēng)險(xiǎn)。它既可以在web或者EJB容器中使用,也能夠在WebLogic,Tomcat,JBoss,Resin,Jetty,Orion和許多其他應(yīng)用服務(wù)器和web容器上使用。

          Spring AOP支持method interception。所支持關(guān)鍵的AOP概念包括:


            Interception:自定義行為能夠在對(duì)接口和類的調(diào)用之前和之后插入。這類似于AspectJ術(shù)語中類似的“around advice”。

            Introduction:指定advice會(huì)導(dǎo)致對(duì)象實(shí)現(xiàn)額外的接口。這混亂了繼承。

            靜態(tài)和動(dòng)態(tài)的pointcuts:在interception發(fā)生的程序執(zhí)行處指定points。靜態(tài)pointcuts concern函數(shù)簽名;動(dòng)態(tài)pointcuts也可以在point被求值的地方考慮函數(shù)的參數(shù)。Pointcuts獨(dú)立interceptors單獨(dú)定義,使得標(biāo)準(zhǔn)interceptor可以應(yīng)用于不同應(yīng)用程序和代碼上下文。

          Spring既支持有狀態(tài)(一個(gè)advised對(duì)象一個(gè)實(shí)例)也支持無狀態(tài)的interceptors(所有advice使用一個(gè)實(shí)例)。

          Spring不支持field interception。這是一個(gè)經(jīng)過深思熟慮的設(shè)計(jì)決定。我總是感覺field interception違反了封裝。我比較傾向于把AOP作為補(bǔ)全物,而不是與OOP沖突的東西。如果在5年或者10年后,我們?cè)贏OP學(xué)習(xí)曲線上走得更遠(yuǎn)了并且覺得應(yīng)該在程序設(shè)計(jì)的桌面上給AOP一個(gè)位置,我不會(huì)驚訝的。(然而在那個(gè)時(shí)候基于語言的解決方案例如AspectJ可能比它們今天看來更加具有吸引力。)

          Spring使用動(dòng)態(tài)代理實(shí)現(xiàn)AOP(其中存在一個(gè)接口)或者在運(yùn)行時(shí)使用CGLIB生成字節(jié)碼(這使得能夠代理類)。兩種方法都能夠在任何應(yīng)用服務(wù)器中使用。

          Spring是第一個(gè)實(shí)現(xiàn)AOP Alliance interfaces的AOP 框架(www.sourceforge.net/projects/aopalliance)。這些是定義在不同AOP框架中能夠互操作interceptors的嘗試。

          在TheServerSide和其他地方有一個(gè)正在進(jìn)行但是不是那么引人注目的爭(zhēng)論,就是這種interception是不是“true AOP”。我倒不怎么在意它叫什么;僅僅需要知道它是否在實(shí)踐中有用就好了。我也樂于稱它為“declarative middleware”(聲明式中間件)。把Spring AOP認(rèn)做簡(jiǎn)單,輕量級(jí)的無狀態(tài)beans的替代物,這樣就不需要monolithic EJB容器了,而這些僅僅是讓你能夠構(gòu)建有你需要的服務(wù)的容器。我不推薦advising任何一個(gè)POJO,對(duì)local SLSBs的類比有助于你理解推薦的粒度。(然而,與EJB不同的是,在恰當(dāng)?shù)巧僖姷那闆r下,你可以自由地把Spring的AOP應(yīng)用到粒度更好的對(duì)象上。)

          因?yàn)镾pring在實(shí)例上advises 對(duì)象,而不是在class loader層面上,使用有不同advice的同一個(gè)類的多個(gè)實(shí)例是可能的,或者與advised實(shí)例一道使用unadvised 實(shí)例。

          可能Spring AOP最常見的應(yīng)用是聲明式事務(wù)管理。這是基于前面描述的TansactionTemplate抽象上的,并且可以給任何POJO提供聲明式事務(wù)管理。取決于事務(wù)策略,底層的機(jī)制可以是JTA,JDBC,Hibernate或者任何其他提供事務(wù)管理的API。

          Spring的聲明式事務(wù)管理類似于EJB CMT,在以下方面有些不同:


            事務(wù)管理能夠應(yīng)用于任何POJO。我們推薦業(yè)務(wù)對(duì)象實(shí)現(xiàn)接口,但是這只是一個(gè)好的編程習(xí)慣的問題,而不是由框架強(qiáng)制的。

            通過使用Spring的事務(wù)API能夠在事務(wù)性POJO中實(shí)現(xiàn)編程回調(diào)。我們?yōu)榇颂峁╈o態(tài)的方法,使用ThreadLoacal變量,因而你不需要傳播諸如EJBContext這樣的context對(duì)象來確保回滾。

            你可以聲明式地定義“回滾規(guī)則”。EJB不會(huì)在未捕捉程序異常的時(shí)候自動(dòng)回滾(僅僅在unchecked exceptions和其他Throwables的時(shí)候),應(yīng)用程序開發(fā)者經(jīng)常需要在任何異常發(fā)生時(shí)回滾。Spring事務(wù)管理讓你能夠聲明式地指定什么異常什么子類能夠?qū)е伦詣?dòng)回滾。缺省的行為和EJB是一致的,但是你能夠在checked和unchecked異常時(shí)自動(dòng)回滾。這個(gè)在最少化自編程回調(diào)代碼方面有很大好處,而回調(diào)依賴于Spring的事務(wù)API(因?yàn)镋JB的編程回調(diào)時(shí)在EJBContext中完成的)。

            事務(wù)管理不綁定于JTA。如前面解釋過的,Spring的事務(wù)管理能夠在不同事務(wù)策略中使用。

          當(dāng)然還可以使用Spring AOP實(shí)現(xiàn)程序特有的aspects。取決于你對(duì)AOP概念的接受程度,決定你是否選擇這么做,而不是Spring的能力,但是它確實(shí)非常有用。我們所見過的成功例子包括:


            自定義的security interception,當(dāng)安全檢查的復(fù)雜度超出了J2EE安全架構(gòu)的能力的時(shí)候

            在開發(fā)中使用的調(diào)試和profiling aspects

            發(fā)送email通知管理員用戶不尋常的舉動(dòng)的Interceptors

          程序自定的aspects能夠成為消除需要許多函數(shù)的樣板代碼的有利武器。

          Spring AOP透明地與Spring BeanFactory概念集成。包含一個(gè)來自Spring BeanFactory對(duì)象地代碼不需要知道它是還是不是advised。和任何對(duì)象一樣,契約實(shí)在接口和對(duì)象實(shí)現(xiàn)中定義的。

          下面的XML片斷展示了如何定義一個(gè)AOP代理:
          代碼:

          <bean id="myTest"
             class="org.springframework.aop.framework.ProxyFactoryBean">
             <property name="proxyInterfaces">
                <value>org.springframework.beans.ITestBean</value>
             </property>
             <property name="interceptorNames">
                <list>
                   <value>txInterceptor</value>
                   <value>target</value>
                </list>
             </property>
          </bean>

          注意bean類的定義總是AOP框架的ProxyFactoryBean,雖然bean的類型在引用中使用或者由BeanFactory的getBean()方法返回時(shí)依賴的是代理接口。(多個(gè)代理方法是被支持的。)ProxyFactoryBean的“interceptorNames”屬性需要一個(gè)字符串列表。(因?yàn)槿绻硎且粋€(gè)“prototype”而不是singleton,有狀態(tài)interceptors可能需要?jiǎng)?chuàng)建新的實(shí)例,所以必須使用Bean的名字而不是bean的引用。)列表中的名字可以是interceptor或者pointcuts(interceptors和有關(guān)它們合適被使用的信息)。列表中的“target”值自動(dòng)創(chuàng)建一個(gè)“invoker interceptor”封裝target對(duì)象。實(shí)現(xiàn)代理接口的是在factory中的bean的名字。這個(gè)例子中的myTest可以和其他bean factory中的bean一樣使用。例如,其他對(duì)象可以使用<ref>元素引用它而且這些引用是由Spring IoC設(shè)置的。

          還可以不用BeanFactory,編程構(gòu)建AOP代理,雖然這個(gè)很少用得上:

          代碼:

          TestBean target = new TestBean();
          DebugInterceptor di = new DebugInterceptor();
          MyInterceptor mi = new MyInterceptor();
          ProxyFactory factory = new ProxyFactory(target);
          factory.addInterceptor(0, di);
          factory.addInterceptor(1, mi);
          // An "invoker interceptor" is automatically added to wrap the target
          ITestBean tb = (ITestBean) factory.getProxy();

          我們相信最好把程序裝配從Java代碼中移出來,而AOP也不例外。

          Spring在它的AOP能力方面的直接競(jìng)爭(zhēng)者是Jon Tirsen的Nanning Aspects(http://nanning.codehaus.org)。

          我覺得AOP作為EJB的替代無提供企業(yè)服務(wù)這個(gè)用法方面的進(jìn)步是重要的。隨著時(shí)間,這將成為Spring很重要的關(guān)注點(diǎn)。
          posted on 2005-10-26 15:56 Sung 閱讀(241) 評(píng)論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 喀什市| 确山县| 余庆县| 无棣县| 邵武市| 咸丰县| 固原市| 临夏县| 湘潭市| 云梦县| 扬中市| 彰化市| 确山县| 澜沧| 桓台县| 新郑市| 张家川| 万盛区| 油尖旺区| 方正县| 德格县| 娱乐| 天水市| 沙坪坝区| 房山区| 鄂州市| 茶陵县| 南溪县| 得荣县| 沙坪坝区| 二手房| 福海县| 辽宁省| 永和县| 正定县| 来宾市| 赣州市| 无极县| 潼南县| 河北省| 仙桃市|