AOSD:應用AOP實現商務邏輯

來源:互聯網
上載者:User
同步自http://www.blogjava.net/AndersLin/archive/2006/06/15/53079.html

(下面是發在javaeye上的文章,因為覺的還有點意思,轉到blog來,關於Domain和AOSD已經有了一些新的想法)

應用Domain開發的系統,通常把邏輯放在Domain Service層中,而Domain Service做兩個工作:
1. 和表現層通訊,表現為把表現層的平面資料(VO)轉換為相關聯的Domain對象,把Domain對象計算的結果轉換成平面資料(VO)返回給表現層;
2.根據Use Case完成商業邏輯的調度。

以下主要討論Use Case的內容。
通常Use Case所描述的Business Flow分為四種:Basic Flow,Alternate Flow,Exception Flow和Extension Flow。
雖然Business Flow可能包含很多領域對象,由於每個use case的目標帶有濃厚的領域邏輯,因而可以通過分析提煉出一個主domain對象。然後重群組轉換來自BA或者PM的BP設計文檔,使其中的Basic Flow基於主domain對象,而把 Alternate Flow,Exception Flow和 Extension Flow基於其它的Domain Service和Domain Object(當然包括Util objects), 最後利用AOP把Alternate Flow, Exception Flow和Extension Flow 與Basic Flow在Service層組織起來。
使用AOP來組織Use Case時,與使用AOP組織技術問題(比如日誌,許可權檢查和交易處理等)不同。
在AOP組織技術問題時,我們不關心join point的目標對象和目標方法以及入口參數。比如:
 

public class BankServiceImpl implements BankService{ 
public void transfer(UserAccount src, UserAccount dist, 
BigDecimal amount)throws Exception{ 
        src.subtract(amount); 
        dist.add(amount); 

//Other code goes here 

< bean id = "  BankService "   class = " org. 
springframework.transaction.interceptor.TransactionProxyFactoryBean " > 
     < property name = " transactionAttributes " >  
          < props >  
< prop key = " transfer " > PROPAGATION_REQUIRED </ prop >                   
          </ props >  
     </ property >  
</ bean >  

我們不關心參數,或者在一些方法重載的地方利用參數來識別區分我們的方法入口。
但當我們利用AOP來組織Use Case時我們關心目標對象和目標方法以及入口參數。因為AOP所要織入的方法是另一個Use Case是另一個Biz Flow。(這個在AOSD中顯示討論的不多,只有在12章12.4.中有提到)
比如我們要在轉帳成功後發手機簡訊通知客戶。那麼在沒有用AOP代碼中我們這樣寫:

public class BankServiceImpl implements BankService{ 
public void transfer(UserAccount src, UserAccount dist, 
BigDecimal change)throws Exception{ 
        src.subtract(change); 
        dist.add(change); 
        SMSService.sendSMS(src, change); 
        SMSService.sendSMS(dist, change); 

//Other code goes here 

Public class SMSService { 
        public static void sendSMS(UserAccount user, BigDecimal change){ 
             Long phone = user.getPhoneNumber(); 
             BigDecimal balance = user.getBalance(); 
             send(phone, change, belance) 

private static void send(Long phone, change, balance){ 
 



事實用User Case的觀點分析,傳送簡訊通知是另一個use case,是轉帳這個use case的extend flow。用AOP的方法應該如下:

public class BankServiceEx { 
public static void notify(UserAccount src, BigDecimal change) { 
        SMSService.sendSMS(src, change); 

//Other code goes here 

public aspect BankServiceAspect { 
pointcut transfer():call(void BankService.transfer(..)); 
        
        after(UserAccount src, UserAccount dist, BigDecimal change) returning : transfer() && args(src, dist, change){ 
        BankServiceEx.notify(src, change); 
BankServiceEx.notify(dist, change); 
        } 


這樣我們完成了兩個用例的分離,兩個用例獨立,可以重用和測試。比如上述簡訊通知用例其實可以被重用到其它情況如:存款,消費,以及銀行分紅等等。
不過可能面臨一個情況是,兩個獨立用例的代碼部分都可能用到某個對象, 那麼在兩個用例中可能重複一部分代碼。雖然從概念上看,不應該重複(在使用用舊的方法實現時不會重複),但從不同use case看,這個重複是值得的。曾經考慮利用代碼產生,直接獲得Local Variable,這樣可以減少重複,但是這個想法是錯誤的,不僅僅是實現上的困難,更重要在於,分離出的傳送簡訊用例便綁定了轉帳用例,依賴於轉帳用例,而無法獨立重用和測試。
這樣,對象、方法以及方法參數構成了一個完整的pointcut,成為不同用例切片的共同入口,相當於一個預留位置。這個時候就需要不同的用例實現人員協調好該入口。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.