Spring框架與AOP思想的研究與應用
摘要 本文對Spring框架中所包含的AOP思想以及事務管理進行了分析,并通過對一個業(yè)務對象實現(xiàn)加鎖/解鎖的操作,說明了動態(tài)代理模式的可行性與有效性。
關(guān)鍵詞 AOP;橫切關(guān)注點;控制反轉(zhuǎn);動態(tài)代理
引言
ASPect Oriented Programming(AOP)是近年來計算機技術(shù)中比較熱門的話題之一。其發(fā)展歷史從學術(shù)領(lǐng)域和研發(fā)機構(gòu)的運用開始,目前流行的Spring應用程序框架將AOP思想融入了整個框架的設計開發(fā)與應用當中。使用Spring框架固然給我們的編程帶來了好處與便利,但是同時存在著一個問題,對于初學者來說,所謂的“控制反轉(zhuǎn)”,不是一個能夠望文生義的好名稱,“依賴注入”也是一樣,也正是因為這樣,不少初學者很難在短時間內(nèi)理解和掌握這些名字和他們的用法,而要使用AOP的功能也需要理解AOP,也比較難?;谝陨显?,我們就會想到,能否簡單地將Spring框架中運用到的優(yōu)秀的理念,巧妙的運用到我們需要使用的地方,而又繞過不容易上手的Spring框架,做到一舉兩得呢?本文就將圍繞著上述提出的問題給出作者的看法和觀點。
AOP思想與面向方面的編程
AOP實際是GoF四人組設計模式的一種擴展,設計模式所追求的是降低代碼之間的耦合度,增加程序的靈活性和可重用性,AOP實際上就是設計模式所追求的目標的一種實現(xiàn)。所謂的分離關(guān)注就是將某一通用的需求功能從不相關(guān)的類之中分離出來;同時,能夠使得很多類共享一個行為,一旦行為發(fā)生變化,不必修改很多類,只要修改這個行為就可以。AOP就是這種實現(xiàn)分散關(guān)注的編程方法,它將“關(guān)注”封裝在“方面”中。
面向?qū)ο蟮木幊蹋∣OP)方法是在面向過程的編程方法基礎(chǔ)上進行的改進,而面向方面編程(AOP)方法又是在面向?qū)ο缶幊蹋∣OP)方法的基礎(chǔ)上進行改進而來的一種創(chuàng)新的軟件開發(fā)方法。AOP和OOP雖然在字面上十分相似,但是卻是面向不同領(lǐng)域的兩種設計思想。OOP(面向?qū)ο缶幊蹋┽槍栴}領(lǐng)域中以及業(yè)務處理過程中存在的實體及其屬性和操作進行抽象和封裝,面向?qū)ο蟮暮诵母拍钍强v向結(jié)構(gòu)的,其目的是獲得更加清晰高效的邏輯單元劃分;而AOP則是針對業(yè)務處理過程中的切面進行提取,例如,某一個操作在各個模塊中都有涉及,這個操作就可以看成“橫切”存在于系統(tǒng)當中。在許多情況下,這些操作都是與業(yè)務邏輯相關(guān)性不強或者不屬于邏輯操作的必須部分,而面向?qū)ο蟮姆椒ê茈y對這種情況做出處理。AOP則將這些操作與業(yè)務邏輯分離,使程序員在編寫程序時可以專注于業(yè)務邏輯的處理,而利用AOP將貫穿于各個模塊間的橫切關(guān)注點自動耦合進來。AOP所面對的是處理過程中的某個步驟或階段,對不同的階段領(lǐng)域加以隔離,已獲得邏輯過程中各部分之間低耦合性的隔離效果,其與面向方面編程在目標上有著本質(zhì)的差異。AOP的核心思想就是將應用程序中的業(yè)務邏輯處理部分同對其提供支持的通用服務,即所謂的“橫切關(guān)注點”進行分離,這些“橫切關(guān)注點”貫穿了程序中的多個縱向模塊的需求。
使用AOP機制進行開發(fā),首先要對方面進行了解,將需求分解成一般關(guān)注點和橫切關(guān)注點,即將核心模塊級的關(guān)注點和系統(tǒng)級的橫切關(guān)注點分離;然后各自獨立的實現(xiàn)這些關(guān)注點;最后用工具將業(yè)務邏輯代碼和橫切關(guān)注點代碼編織到一起,形成最終的程序。通過面向方面的編程可以減少編碼時間和重復。
目前已經(jīng)形成的Spring框架
1、Spring框架的特點
Spring框架目前如此流行,一方面的原因在于Spring提供了一套全面并且十分成熟的輕型應用程序基本框架,并且對復雜的應用開發(fā)提供了有力的支持。除此之外,從實際應用開發(fā)角度來看,Spring最大的優(yōu)勢在于它是從實際項目開發(fā)經(jīng)驗中抽取的,其提供了豐富的類庫,可大大節(jié)省編碼量,它是一種高效的、可高度重用的應用框架。Spring框架中目前最吸引人也是該應用框架最具特色的地方就是名為控制反轉(zhuǎn)(IOC=Inverse Of Control)或者依賴注入(DI=Dependence Injection)的設計思想,這是一種相當優(yōu)秀的設計思想,即“好萊塢”原則:不用你主動來找我,我會通知你。但是,僅僅憑借著這樣一個單純的設計模式并不能使得Spring如此成功,Spring最成功的地方,還是目前使用最為廣泛的AOP應用,也就是Spring中基于AOP實現(xiàn)的業(yè)務管理機制,也正是由于這一點,使得Spring AOP成為應用框架中極其閃光的一個亮點。
2、AOP思想在Spring框架中的體現(xiàn)
文章前面已經(jīng)講述了AOP的概念以及什么叫做所謂的“橫切”關(guān)注點,事務管理就是J2EE應用中一個橫切多個對象的橫切關(guān)注點的例子。
2.1 事務管理
對于J2EE應用程序而言,事務的處理一般有兩種模式:依賴特定事務資源的事務處理與依賴容器的參數(shù)化事務管理。在這里我們略去對第一種處理方式的說明,直接對第二種方式,即依賴容器的參數(shù)化事務管理來闡述筆者的觀點。
Spring事務管理究竟能帶給我們什么?
了解Spring的人們都知道,對于傳統(tǒng)的基于事務資源的事務處理而言,Spring并不會產(chǎn)生什么影響,我們照樣可以成功編寫并且運行這樣的代碼。
對于依賴容器的參數(shù)化事務管理而言,Spring則可以用來幫助實現(xiàn)對事務的管理而無須使用EJB。Spring本身也是一個容器,只是相對EJB容器所要付出的代價而言,Spring屬于輕量級容器,它能夠替代EJB,通過使用AOP來提供聲明式事務管理,即可通過Spring實現(xiàn)基于容器的事務管理(從本質(zhì)上來講,Spring的事務管理是基于動態(tài)AOP)。Spring與EJB最大的區(qū)別在于:第一,Spring可以為任意的Java Class實現(xiàn)事務管理而無須轉(zhuǎn)換成標準的EJB;第二,Spring事務管理并不依賴特定的事務資源從而使得系統(tǒng)的應用與部署更佳靈活。
2.2動態(tài)代理機制的實現(xiàn)
Spring框架中所提供的AOP支持,是基于動態(tài)AOP機制實現(xiàn)的,即通過動態(tài)Proxy模式,在目標對象的方法調(diào)用前后插入相應的處理代碼。AOP代理可以是基于JDK動態(tài)代理,也可以是基于CGLIB代理。Spring默認使用的是基于Java Dynamic Proxy模式實現(xiàn),這樣任何的接口都能被代理。基于Spirng框架的應用程序開發(fā),程序員會有一種自然的傾向性來實現(xiàn)面向接口編程而不是類,業(yè)務對象通常也是實現(xiàn)一個或者多個接口,這也是一種良好的編程習慣。Spring也可以基于CGLIB實現(xiàn)AOP代理,這樣所代理的是類而不是接口。如果一個業(yè)務對象沒有實現(xiàn)某一個接口,那么CGLIB將被使用。
我們先來分析一下Spring事務管理機制的實現(xiàn)原理。由于Spring內(nèi)置AOP默認使用動態(tài)代理模式實現(xiàn),我們就先來分析一下動態(tài)代理模式的實現(xiàn)方法。動態(tài)代理模式的核心就在于代碼中不出現(xiàn)與具體應用層相關(guān)聯(lián)的接口或者類引用,如上所說,這個代理類適用于任何接口的實現(xiàn)。下面我們來看一個例子。 public class TxHandler implements InvocationHandler {
private Object originalObject; |
下面我們來分析一下上述代碼的關(guān)鍵所在。
首先來看一下這段代碼:
return Proxy.newProxyInstance( |
java.lang.reflect.Proxy.newProxyInstance方法根據(jù)傳入的接口類型(obj.getClass.getInterfaces())動態(tài)構(gòu)造一個代理類實例返回,這也說明了為什么動態(tài)代理實現(xiàn)要求其所代理的對象一定要實現(xiàn)一個接口。這個代理類實例在內(nèi)存中是動態(tài)構(gòu)造的,它實現(xiàn)了傳入的接口列表中所包含的所有接口。
再來分析以下代碼:
public Object invoke(Object proxy, Method method, Object[] args) |
InvocationHandler.invoke方法將在被代理類的方法被調(diào)用之前觸發(fā)。通過這個方法,我們可以在被代理類方法調(diào)用的前后進行一些處理,如代碼中所示,InvocationHandler.invoke方法的參數(shù)中傳遞了當前被調(diào)用的方法(Method),以及被調(diào)用方法的參數(shù)。同時,可以通過method.invoke方法調(diào)用被代理類的原始方法實現(xiàn)。這樣就可以在被代理類的方法調(diào)用前后寫入任何想要進行的操作。
Spring的事務管理機制實現(xiàn)的原理,就是通過這樣一個動態(tài)代理對所有需要事務管理的Bean進行加載,并根據(jù)配置在invoke方法中對當前調(diào)用的方法名進行判定,并在method.invoke方法前后為其加上合適的事務管理代碼,這樣就實現(xiàn)了Spring式的事務管理。Spring中的AOP實現(xiàn)更為復雜和靈活,不過基本原理是一致的。