使用AOP實現日誌和權限認證組件

使用AOP實現日誌和權限認證組件

技術背景:

Aspect Oriented Programming(AOP)是近來較爲熱門的一個話題。AOP,國內大致譯作“面向方面編程”。

AOP、OOP在字面上雖然非常類似,但卻是面向不同領域的兩種設計思想。OOP(面向對象編程)針對業務處理過程的實體及其屬性和行爲進行抽象封裝,以獲得更加清晰高效的邏輯單元劃分。

AOP則是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。這兩種設計思想在目標上有着本質的差異。

上面的陳述可能過於理論化,舉個簡單的例子,對於“僱員”這樣一個業務實體進行封裝自然是OOP/OOD的任務,我們可以爲其建立一個“Employee”類,並將“僱員”相關的屬性和行爲封裝其中。而用AOP設計思想對“僱員”進行封裝將無從談起。同樣,對於“權限檢查”這一動作片斷進行劃分,則是AOP的目標領域。而通過OOD/OOP對一個動作進行封裝,則有點不倫不類。換而言之,OOD/OOP面向名詞領域,AOP面向動詞領域。

AOP和OOD/OOP並不衝突,我們完全可以在一個應用系統中同時應用OOD/OOP和AOP設計思想,通過OOD/OOP對系統中的業務對象進行建模,同時通過AOP對實體處理過程中的階段進行隔離處理。即使不是OOD/OOP,而是在傳統的POP(面向過程編程)中,AOP也能起到同樣的作用。

 

將不同階段領域加以分隔,這是否就算是AOP呢?

AOP還有另外一個重要特點:源碼組成無關性。

倘若應用中通過某個具體的業務邏輯類實現了獨立的權限檢查,而請求調度方法通過預編碼調用這個權限模塊實現權限管理。那麼這也不算是AOP。對於AOP組件而言,很重要的一點就是源碼組成無關性,所謂源碼組成無關性,體現在具體設計中就是AOP組件必須與應用代碼無關,簡單來講,就是應用代碼可以脫離AOP組件獨立編譯。爲了實現源碼組成無關性,AOP往往通過預編譯方式和運行期動態代理模式實現。考慮到使用的方便,以及本組件面對的爲採用OOP設計的MIS系統,所以,我選擇了使用JDK本身提供的動態代理API實現。

 

發明目標:

現在的數據庫應用系統越來越龐大,採用多層結構,分層開發,web端的開發人員開發頁面。

中間層的開發人員開發業務邏輯組件和數據訪問組件。分層開發的目的在於使各個層次不相互依賴,可以獨立的按照進度要求工作,這也是現在流行的所謂的軟件工廠的開發思想。但真正要實現各個層次的解藕,基本上是很困難的,這跟開發人員的水平和系統的特點有關,同時,有一些通用組件比如日誌和權限驗證,往往在各個層次,多個組件中都要使用,這也就是Aspect(切面)的存在的原因。

按照原來的OOP的編程方式,會在代碼中大量的存在調用日誌,權限的代碼。即使設計得很精妙,也不能實現業務組件和日誌,權限組件的完全解藕,因爲組件之間一旦調用就會產生藕和,而使用AOP的設計,通過Interceptor攔截事先定義好的組件中需要記錄日誌,需要驗證權限的Action,系統自動的去作,這樣業務組件就可以和權限,日誌組件毫無關聯,各自開發各自的,哪一端發生了變動都不影響另一端,相反,如果象過去的那樣設計,一旦寫日誌,驗證權限的方式發生變化,調用的參數有改變了,你需要修改大量的源碼。產生BUG的可能性就大大的提高了。

 

發明內容:

因爲是使用JDK的動態代理技術,所以,要求業務組件必須要有接口層,這種強制性的要求使業務組件的設計者必須使用面對對象的設計,從而使得系統有明確的抽象層和實現層之分。使用者通過調用AOPFactory,返回一個被代理的動態對象,然後通過代理對象處理業務邏輯,一旦調用業務方法,則定義好的攔截器會攔截這個action,在攔截器中會自動的對這個action進行預處理(before)和後處理(after),以及異常處理,

而權限驗證針對的就是預處理,日誌針對的就是後處理。這樣業務組件只需要關注他自己的業務就行了,不用再考慮日誌和權限了,

打個比喻,就像EJB,你只需要編寫業務邏輯代碼,而事務處理,安全認證這些,你都不要考慮了,統統都由EJB容器幫你去做,這裏也是如此。

 

具體實施方式

    業務組件抽象接口(強制要求使用接口定義,使得設計上更好的符合OOD)

    public interface TestBusinessBase {

        public void sendFile();

}

    業務組件的實現

    public class TestBusiness implements TestBusinessBase{

         public void sendFile()

        {

             System.out.println("現在發送文件");

}

 

使用

public class Test {

      public static void main(String[] args) {

        Object businessProxy = AOPFactory.getAOPProxyedObject(

                "aoptest.TestBusinessUser");

        TestBusinessBase proxyBusiness = (TestBusinessBase) businessProxy;

        proxyBusiness.sendFile(); 

    }

}

可見,只需要在產生業務組件對象的時候調用代理工廠的方法返回一個該業務組件的代理類,就可以自動的進行權限和日誌的工作了,而在業務組件TestBusiness中完成看不到有關權限和日誌的代碼,完全實現了組件之間的解藕。

性能上,由於JDK1.4的反射的性能已經有了很大的提高,所以利用發射產生對象的開銷並不是很大。而且在一些性能要求很高的場景下,還可以使用對象池技術。使用Jmeter作壓力測試,10000個併發下平均值是422毫秒。和原來的相差100毫秒以內。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章