在AOSD:應用AOP實現業務邏輯中, 我提出關注的接口; 其原文在javaeye上的討論狼平方也提出可以用event,或者intercepter。 當然不同的方式可以解決不同的問題。這里要討論一下AspectJ和Event以及intercepter的不同。
1. 先來看看event的方式:需要兩個對象Event和EventHandler(EventListener),event和eventHandler,屬于數據契約。換句話說,犧牲了編譯檢查的好處,當然可以應對變化時有一定的好處。一旦需求變化,代碼上的變動需要的工作量不少,更為嚴重的是,如狼平方所說的侵入性太強。 2 接著看interceptor的AOP,相對于Event方式,雖然都是基于數據契約,都給自己做轉型,但是代碼量少了(因為代碼生成),重要的是沒有event那樣的侵入性。 3. 狼平方做了改進,利用AOP來做brocastEvent的工作。需要做的工作還是很多,甚至我以為這個工作還不如直接用Interceptor來得直接。
如我在小議領域模型(Domain Model) 所說的Domain Service處理兩個邏輯:業務規則和流程邏輯,而AOSD:應用AOP實現業務邏輯要試圖解決的問題是流程上邏輯,而以上無論是那種方式,都無法解決一個問題:流程信息。 假定現有兩個流程如下:
這里我們關注的目標方法是doSomeAction(),在doSomeAction中我們希望做些額外的工作, 以狼平方的例子,比如:financialService.createRequestOfMoney(...); 那么無論是用event:
還是interceptor:
我們注意到,這樣做的結果是在bizProcessA()和bizProcessB()的不同業務流程都將導致執行 financialService.createRequestOfMoney 不過我們的流程邏輯要求是: 在bizProcessA()的流程下,執行financialService.createRequestOfMoney 而在bizProcessB的流程下,不執行financialService.createRequestOfMoney。
很明顯無論是之上event,還是interceptor的AOP都無法解決這個問題。
面對這樣的需求,就需要改進或者重構: 1. 最簡單也最直接改doSomeAction(...)為doSomeAction(...boolean flag)。很明顯這樣的做法很不理想 2. 來點OO的, 將doSomeAction(...)分出去,作為一個接口,采用多態解決。不過依然需要解決動態加載問題,處理起來又需要費點手段。
真的只有這兩個手段了嗎?不!還有,那就是AspectJ AspectJ提供了如下 within withincode withincode cflow cflowbelow 幾個內置的pointcut,將可以做到我們要的效果,代碼如下:
很顯然,AspectJ提供了AOSD所需要的軍火。
BTW:本文不針對狼平方同學,只是借由其兩篇blog討論開來,解釋了AspectJ優點,以及為什么AspectJ是實現AOSD的最佳也是唯一軍火。 事實上很多時候,解決問題的方法有很多,本文旨在闡明AOSD為我們提供了另一條思路。歡迎討論和拍磚!
另補上我在javaeye討論貼的完整例子代碼,下載。