Java-Android-jwebee
          Java-Android-jwebee
          對IT人來說,要成為一個優(yōu)秀的技術(shù)型管理者,除了需要具備扎實的技術(shù)基礎(chǔ)之外,還應(yīng)該培養(yǎng)良好的人際關(guān)系能力、談判與溝通技能、客戶關(guān)系與咨詢技能、商業(yè)頭腦和財務(wù)技能以及創(chuàng)新意識,此外還要有巧妙的激勵技巧和化解沖突與解決突發(fā)問題的能力.

          ????? AOP(Aspect Oroented Programming,面向切面編程)是消除代碼重復(fù)的一種方法。

          ????? AOP是OOP的延續(xù),是Aspect Oriented Programming的縮寫,意思是面向方面編程。AOP實際是GoF設(shè)計模式的延續(xù),設(shè)計模式孜孜不倦追求的是調(diào)用者和被調(diào)用者之間的解耦,AOP可以說也是這種目標(biāo)的一種實現(xiàn)。

            舉例:假設(shè)有在一個應(yīng)用系統(tǒng)中,有一個共享的數(shù)據(jù)必須被并發(fā)同時訪問,首先,將這個數(shù)據(jù)封裝在數(shù)據(jù)對象中,稱為Data Class,同時,將有多個訪問類,專門用于在同一時刻訪問這同一個數(shù)據(jù)對象。

            為了完成上述并發(fā)訪問同一資源的功能,需要引入鎖Lock的概念,也就是說,某個時刻,當(dāng)有一個訪問類訪問這個數(shù)據(jù)對象時,這個數(shù)據(jù)對象必須上鎖Locked,用完后就立即解鎖unLocked,再供其它訪問類訪問。

            使用傳統(tǒng)的編程習(xí)慣,我們會創(chuàng)建一個抽象類,所有的訪問類繼承這個抽象父類,如下:

          abstract class Worker{

            abstract void locked();
            abstract void accessDataObject();
            abstract void unlocked();

          }

          AOP的缺點
          ?
          ????? accessDataObject()方法需要有“鎖”狀態(tài)之類的相關(guān)代碼。

          ????? Java只提供了單繼承,因此具體訪問類只能繼承這個父類,如果具體訪問類還要繼承其它父類,比如另外一個如Worker的父類,將無法方便實現(xiàn)。
          重用被打折扣,具體訪問類因為也包含“鎖”狀態(tài)之類的相關(guān)代碼,只能被重用在相關(guān)有“鎖”的場合,重用范圍很窄。

          ????? 仔細(xì)研究這個應(yīng)用的“鎖”,它其實有下列特性:
          ????? “鎖”功能不是具體訪問類的首要或主要功能,訪問類主要功能是訪問數(shù)據(jù)對象,例如讀取數(shù)據(jù)或更改動作。
          ????? “鎖”行為其實是和具體訪問類的主要功能可以獨立、區(qū)分開來的。
          ????? “鎖”功能其實是這個系統(tǒng)的一個縱向切面,涉及許多類、許多類的方法。如下圖:
          ?

            因此,一個新的程序結(jié)構(gòu)應(yīng)該是關(guān)注系統(tǒng)的縱向切面,例如這個應(yīng)用的“鎖”功能,這個新的程序結(jié)構(gòu)就是aspect(方面)

            在這個應(yīng)用中,“鎖”方面(aspect)應(yīng)該有以下職責(zé):

            提供一些必備的功能,對被訪問對象實現(xiàn)加鎖或解鎖功能。以保證所有在修改數(shù)據(jù)對象的操作之前能夠調(diào)用lock()加鎖,在它使用完成后,調(diào)用unlock()解鎖。

          AOP應(yīng)用范圍

            很明顯,AOP非常適合開發(fā)J2EE容器服務(wù)器,目前JBoss 4.0正是使用AOP框架進(jìn)行開發(fā)。
            具體功能如下:
          Authentication 權(quán)限
          Caching 緩存
          Context passing 內(nèi)容傳遞
          Error handling 錯誤處理
          Lazy loading 懶加載
          Debugging  調(diào)試
          logging, tracing, profiling and monitoring 記錄跟蹤 優(yōu)化 校準(zhǔn)
          Performance optimization 性能優(yōu)化
          Persistence  持久化
          Resource pooling 資源池
          Synchronization 同步
          Transactions 事務(wù)

          AOP有必要嗎?

            當(dāng)然,上述應(yīng)用范例在沒有使用AOP情況下,也得到了解決,例如JBoss 3.XXX也提供了上述應(yīng)用功能,但是沒有使用AOP。

            但是,使用AOP可以讓我們從一個更高的抽象概念來理解軟件系統(tǒng),AOP也許提供一種有價值的工具。可以這么說:因為使用AOP結(jié)構(gòu),現(xiàn)在JBoss 4.0的源碼要比JBoss 3.X容易理解多了,這對于一個大型復(fù)雜系統(tǒng)來說是非常重要的。

            從另外一個方面說,好像不是所有的人都需要關(guān)心AOP,它可能是一種架構(gòu)設(shè)計的選擇,如果選擇J2EE系統(tǒng),AOP關(guān)注的上述通用方面都已經(jīng)被J2EE容器實現(xiàn)了,J2EE應(yīng)用系統(tǒng)開發(fā)者可能需要更多地關(guān)注行業(yè)應(yīng)用方面aspect。

          AOP具體實現(xiàn)

            AOP是一個概念,并沒有設(shè)定具體語言的實現(xiàn),它能克服那些只有單繼承特性語言的缺點(如Java),目前AOP具體實現(xiàn)有以下幾個項目:

            AspectJ (TM): 創(chuàng)建于Xerox PARC. 有近十年歷史,成熟
            缺點:過于復(fù)雜;破壞封裝;需要專門的Java編譯器。

            動態(tài)AOP:使用JDK的動態(tài)代理API或字節(jié)碼Bytecode處理技術(shù)。

            基于動態(tài)代理API的具體項目有:
            JBoss 4.0 JBoss 4.0服務(wù)器
            nanning 這是以中國南寧命名的一個項目,搞不清楚為什么和中國相關(guān)?是中國人發(fā)起的?

            基于字節(jié)碼的項目有:
            aspectwerkz 
            spring ?

          定義和概念

          AOP像大多數(shù)編程范式一樣,有她自己的詞匯表。下表定義了許多在閱讀AOP相關(guān)內(nèi)容或者應(yīng)用AOP工作時可能會遇到的詞匯和短語。這些定義不是Spring特有的。
          ?
          表9.1 AOP定義

          Term 術(shù)語
          Definition 定義
          Concern A particular issue
          (關(guān)注特定問題)
          感興趣應(yīng)用的特定問題、概念、范圍。例如,事務(wù)管理、持久化、日志、安全等。
          Crosscutting Concern
          (橫切關(guān)注點)
          在關(guān)注點實現(xiàn)中貫穿了很多類,這在面向?qū)ο螅∣OP)中通常很難實現(xiàn)和維護(hù)。
          Aspect
          (切面)
          模塊化的橫切關(guān)注點,通過代碼的聚合和隔離實現(xiàn)。
          Join Point
          (連接點)
          在程序或者類執(zhí)行時的一個點。在Spring的AOP實現(xiàn)中,連接點總是一個方法調(diào)用。其他的例子包括訪問字段(包括實例中字段的讀寫),變量和異常處理。
          Advice
          (通知)
          特定連接點所采取的動作。Spring有幾種不同類型的通知,包括around、before、throws和after returning。在這幾種類型的通知中,around是最強(qiáng)大的,在方法調(diào)用的前后都有執(zhí)行一些操作的機(jī)會。之前用到的TraceInterceptor就是around類型的通知,它實現(xiàn)了AOP聯(lián)盟的MethodInterceptor接口。通過實現(xiàn)下面的Spring接口可以使用其他類型的通知:
          ????????? MethodBeforeAdvice
          ????????? ThrowsAdvice
          ????????? AfterReturningAdvice
          Pointcut
          (切入點)
          連接點的集合,這些連接點確認(rèn)何時一個通知將會觸發(fā)。切入點通常使用正則表達(dá)式或者是通配符語法。
          Introduction
          (引入)
          添加字段或者方法到一個通知類。Spring允許你在任何通知對象上引入新的接口。例如,你可以使用引入以便讓任意對象實現(xiàn)IsModified接口,來簡化緩存。
          Weaving
          (組織)
          裝配切面來創(chuàng)建一個被通知對象。可以在編譯期間完成(像AspectJ做的那樣)也可以在運(yùn)行時完成。本章后面的組織策略部分詳細(xì)討論不同的組織策略(也就是實現(xiàn)AOP)。
          Interceptor
          (攔截器)
          一種AOP實現(xiàn)策略,對與特點的連接點,可能存在一個攔截器鏈。
          AOP Proxy
          (AOP代理)
          AOP框架創(chuàng)建的對象,包括通知。在Spring中,一個AOP代理可能是JDK動態(tài)代理或者是CGLIB代理。
          Target Object
          (目標(biāo)對象)
          包含連接點的對象。在使用攔截的框架中,它是在攔截器鏈末端的對象實例。也叫做被通知對象或者被代理對象。
          ?
          下個部分是關(guān)于切入點的,切入點是應(yīng)用通知的規(guī)則。因為Spring的AOP是基于攔截器的,所以我將會用攔截器來代替通知說明問題。
          ?

          切入點

          切入點是AOP的重要部分。他們能讓你確認(rèn)在何時何地調(diào)用攔截器。在某種意義上,他們通常都像是聲明式的確認(rèn),但是相比確認(rèn)要驗證的字段,你更應(yīng)該確認(rèn)要檢查的方法。在上面的表格中,切入點被定義為:確認(rèn)何時一個通知(攔截器)將觸發(fā)的一組連接點的集合。由于Spring只支持方法調(diào)用連接點,所有在Spring中切入點也就是應(yīng)用攔截器的方法的聲明。
          ?
          在Spring的AOP中定義切入點的最簡單方法是,在context文件中使用正則表達(dá)式。下面的例子為數(shù)據(jù)處理操作定義了一個切入點。
          ?
          .*save.*
          .*remove.*
          ?
          這個切入點告訴我們,攔截方法的方法名應(yīng)該以save或者remove開始。
          ?
          ? 注意
          上例的JdkRegexpMethodPointcut類,需要J2SE1.4,它內(nèi)置了正則表達(dá)式支持。也可以改用Perl5RegexpMethodPointcut,它需要Jakarta ORO包(已經(jīng)在MyUsers里包括了)。
          ?
          大多數(shù)情況下,你不必像上面一樣定義單獨的切入點。Spring提供了一個advisor的類,它在同一個bean中封裝了攔截器和切入點。
          ?
          對正則表達(dá)式定義的切入點來說,可以使用RegexpMethodPointcutAdvisor這個advisor。下面是一個RegularExpressionPointcutAdvice的例子,它在用戶信息被保存的時候觸發(fā)一個NotificationInterceptor
          ?
          .*saveUser
          ?
          目前,RegexpMethodPointcutAdvisor只支持Perl5的正則表達(dá)式規(guī)則,也就是說,如果你要用它,那么在你的classpath下必須要有jakarta-oro.jar 這個包。在org.springframework.aop.support包中有一個詳細(xì)的切入點列表和他們對應(yīng)的advisor。
          ?

          組織策略

          組織(weaving)是將切面應(yīng)用到目標(biāo)對象的過程。下面的列出了實現(xiàn)AOP的基本策略,按從簡單到復(fù)雜排列。
          ?
          ? 注意
          在這部分大多數(shù)信息都以J2EE without EJB中的信息為基礎(chǔ)。
          ????????? JDK動態(tài)代理
          ????????? 動態(tài)字節(jié)碼生成
          ????????? 自定義類加載器
          ????????? 語言擴(kuò)展
          這些策略在各種不同的開源AOP框架中都有實現(xiàn)。
          ?
          ?
          ? 注意
          這些框架最出色的部分是他們對在API中使用共同的標(biāo)準(zhǔn)很感興趣。為了支持這一想法,他們創(chuàng)建了AOP聯(lián)盟計劃,定義了大量用來實現(xiàn)的接口。可以閱讀AOP聯(lián)盟的成員列表,看看都哪些框架在這個計劃中。
          ?
          下面詳細(xì)描述各種組織策略。
          ?
          JDK 動態(tài)代理
          ?
          動態(tài)代理是J2SE1.3以上版本的內(nèi)置特性。它允許你憑空(on-the-fly)創(chuàng)建一個或更多接口的實現(xiàn)。動態(tài)代理內(nèi)嵌在JDK中,排除了在各種環(huán)境下奇怪行為帶來的風(fēng)險。JDK動態(tài)代理有個限制就是它只能代理接口不能代理類。當(dāng)然如果你用接口很好的設(shè)計了你的應(yīng)用,那這就不是一個問題。
          ?
          使用動態(tài)代理的時候還要用一些反射機(jī)制,但在J2SE1.4以上的JVM中這點性能消耗可以忽律不計。在代理接口時,Spring默認(rèn)使用JDK動態(tài)代理。dynaop這個項目在代理接口時使用這個策略。
          ?
          更多關(guān)于動態(tài)代理的信息,可以查看Java 2 SDK文檔。
          ?
          字節(jié)碼動態(tài)生成
          ?
          在代理類時,Spring采用字節(jié)碼動態(tài)生成。CGLIB (Code Generation Library)是做這個的一個流行工具。它通過動態(tài)生成子類來攔截方法。這些生成的子類改寫父類的方法,用鉤子(hook)調(diào)用攔截器實現(xiàn)。Hibernate廣泛使用CGLIB,并且已經(jīng)被證明是可靠的J2EE解決方案。
          ?
          ?????? 一個限制是,動態(tài)生成的子類不能改寫和代理final方法。
          ?
          自定義類加載器
          ?
          使用自定義的類加載器,可以讓你通知所創(chuàng)建的實例。這十分強(qiáng)大,因為它提供了修改新操作行為的機(jī)會。Jboss AOP和AspectWerkz用的這種方式,根據(jù)在XML文件中定義的方式加載和組織類。
          這種方式最主要的威脅存在于,J2EE服務(wù)器必須仔細(xì)地控制類加載層次,在一個服務(wù)器上工作很好可以在另一個服務(wù)器上就不能正常工作。
          ?
          語言擴(kuò)展
          AspectJ是java AOP框架實現(xiàn)的排頭兵。它包含了語言的擴(kuò)展并且使用自帶的編譯器,而不是使用簡單的策略進(jìn)行切面的組織。
          ?
          雖然AspectJ是非常強(qiáng)大和成熟的AOP實現(xiàn),它的語法還是有點復(fù)雜而且也不是很直觀。然而,AOP本身就不是很直觀,嘗試用一種新的語言去實現(xiàn)更顯困難。這種方式的另外一個限制是學(xué)習(xí)一門新語言的學(xué)習(xí)曲線。但是,如果你想要完整的AOP功能,包括字段級的攔截,AspectJ可能會成為你最好的伙伴。在本章的末尾,介紹了集成AspectJ和Spring。
          ?
          在Spring的AOP實現(xiàn)中,采取務(wù)實的8-2原則,它解決了最常用的部分,把更專業(yè)的部分留給其他AOP框架,而不是試圖解決所有的問題。
          ?

          便于應(yīng)用的代理bean

          ?
          像前面提到的,為了把通知應(yīng)用到context文件里定義的bean上,這些bean必須要通過代理。Spring包含很多支撐類(或者說是Proxy Beans)來簡化代理。首先是ProxyFactoryBean,它允許你指明要被代理的bean和要應(yīng)用的攔截器。下面的例子使用了ProxyFactoryBean來創(chuàng)建一個業(yè)務(wù)對象的代理。
          ?
          上面的例子在target屬性上使用了內(nèi)置bean(inner-bean)。內(nèi)置bean是在代理中隱藏業(yè)務(wù)對象的一個簡便方法,因此在從ApplicationContext中抽取出業(yè)務(wù)bean時,它總是值得推薦的方法。
          ?
          TransactionProxyFactoryBean是最有用和最常用的代理Bean。這個bean允許你使用AOP在目標(biāo)對象上聲明式地定義事務(wù)。事務(wù)特性在之前只能通過EJB容器管理的事務(wù)(CMT)來獲得。TransactionProxyFactoryBean的使用將會在AOP例子練習(xí)部分說明。
          ?
          ?
          自動代理 Bean
          ?
          前述的代理類為單個bean提供了簡單的操作,但是如果你想代理多個bean或者上下文中所有的bean時怎么辦?Spring提高了兩個類(在org.springframework.aop.framework.autoproxy包中)簡化這種處理。
          ?
          ?????? 第一個是BeanNameAutoProxyCreator,它允許你指明一個bean名稱列表作為屬性。這個屬性支持字面(實際的bean名)和像*Manager的通配符。可以用interceptorNames屬性設(shè)置攔截器。
          <>
          class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
          *Manager
          loggingInterceptor
          ?
          ?????? 第二個,更通用的多bean代理創(chuàng)建者是DefaultAdvisorAutoProxyCreator。使用這個代理類,簡單的在context文件中定義就可以。
          <>
          class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
          ?
          不像BeanNameAutoProxyCreator,你不能指明想用的攔截器。它將會檢查context文件中的每一個advisor,指出他們的切入點是否可以用到其他的bean上。更多關(guān)于advisor的信息,請參閱Spring參考文檔。
          ?
          ?
          AOP實際應(yīng)用的例子
          ?
          這部分包括了幾個使用AOP管理應(yīng)用中橫切關(guān)注點的例子,這些關(guān)注點包括事務(wù)、緩存、事件通知。
          ?

          事務(wù)

          ?
          指明操作應(yīng)該在事務(wù)中進(jìn)行,可能導(dǎo)致在DAO中大量的復(fù)制。使用事務(wù)時,傳統(tǒng)的方式需要在數(shù)據(jù)操作方法中進(jìn)行大量的tx.begin()tx.commit()調(diào)用。Spring和AOP帶來的一個好消息是,可以通過在一個位置聲明及配置的方法加強(qiáng)事務(wù)管理。
          ?
          ?????? 可能還不了解,但是你已經(jīng)在快速開始那一章,MyUsers這個應(yīng)用中使用過AOP了。使用Spring的AOP和TransactionProxyFactoryBean,可以讓你聲明式地在userManager這個bean上指明事務(wù)屬性。下面的代碼顯示了一個userManager重構(gòu)過的版本,這里使用了事務(wù)模板bean內(nèi)置bean
          < abstract="true">
          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          PROPAGATION_REQUIRED
          PROPAGATION_REQUIRED
          PROPAGATION_REQUIRED,readOnly
          ?
          ?
          警告
          ?
          ?????? 在1.1.2版本之前,可以使用lazy-init=”true”來代替abstract=”true”在1.1.2和之后的版本,Spring會拋出異常:java.lang.IllegalArgumentException: ‘target’ is required。1.1.1版本和之前的版本允許使用lazy-init=”true”來代替abstract=”true”屬性。1.1版本添加abstract屬性的目的是標(biāo)記父層bean不會預(yù)先初始化。


          jwebee

          我的個人網(wǎng)站
          posted on 2006-11-28 09:17 周行 閱讀(2051) 評論(1)  編輯  收藏 所屬分類: IT技術(shù)

          FeedBack:
          # re: AOP 面向切面編程
          2009-02-26 20:15 | 雨川
          好,頂一下  回復(fù)  更多評論
            
          Java-Android-jwebee
          主站蜘蛛池模板: 柳州市| 信宜市| 东明县| 丹巴县| 无为县| 琼中| 监利县| 都匀市| 车致| 兰溪市| 自贡市| 绥棱县| 阿拉善盟| 天长市| 衡阳市| 禹州市| 珲春市| 吉安县| 龙门县| 上高县| 阜南县| 旅游| 巫山县| 泰兴市| 洛阳市| 图片| 波密县| 逊克县| 屏山县| 怀仁县| 威远县| 万荣县| 万年县| 白银市| 枣庄市| 四会市| 平果县| 会理县| 和田市| 深水埗区| 雷波县|