在上一篇文章里,我們使用了基于事件傳遞的機制來對企業應用的子系統進行解耦,但是由于需要強制地繼承或者實現一個廣播事件的接口EventBrocast,實際上,就職責分離和功能單一的角度來看,前篇文章中的例子中,這個機制對OrderService侵入太大了,我們必須尋找更為有效的方法,不需要程序實現某個接口或繼承某個超類來完成這個工作,這一切必須對具體程序完全透明,這個責任誰能承擔呢,毫無疑問,歷史的重擔就落在了AOP身上 ;) 。下面我們來看看具體的實現:
OrderService已經實現,除了訂單的處理,沒有任何的職責,為了完成事件的廣播,必須要有一個途徑能夠攔截到OrderService的所有方法調用,然后分析調用的語義(參數),并根據這些內容給廣播出去。而恰好,AOP組織統一的接口MethodInterceptor可以完成這個功能。于是上篇文章的程序可以這樣修改:
// 訂單服務只負責做好自己的事
public class OrderService {
public Order saveOrder(Order order){
。。。。處理訂單
。。。保存
}
}
而為了攔截任何的方法調用,則實現了攔截器EventBrocaster:
public class EventBrocaster extends LifeEventBrocast implements MethodInterceptor {
private List eventListeners;
public void setEventListener(List list){
this.eventListeners=list;
}
public List geteEventListeners(){
return eventListeners;
}
public Object invoke(MethodInvocation invoke) {
obj = invoke.proceed();// 執行被攔截的方法完成業務操作
Object[] params = invoke.getArguments();
Object param = params.length > 1 ? params : params[0];
Event le = new Event(param, eventType);
brocast(le);// 廣播
}
}
事件偵聽器:
public OrderEventListener implements EventListener{
private FinancialService financialService;
public void setFinancialService(FinancialService fs){
this.financialService=fs;
}
public void performed(Event e){
Order order =(Order) e.getObject();
financialService.createRequestOfMoney(order.getAmount()
);
}
}
然后,在Spring配置里將這些組件全部連接起來:
1.OrderService實現:
<bean id="orderServiceImpl" class="OrderService" autowire="byName">
</bean>
2. 聲明OrderService代理:
<bean id="orderService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="orderServiceImpl"/>
</property>
<property name="interceptorNames"> <!--攔截器列表-->
<list>
<value>eventBrocaster</value>
</list>
</property>
<property name="singleton">
<value>true</value>
</property>
</bean>
3.事件廣播攔截器
<bean id="eventBrocaster" class="com.wolfsquare.core.service.EventBrocaster" singleton="true">
<property name="lifecycleListeners">
<list>
<ref bean="orderEventListener"/>
</list>
</property>
</bean>
4.具體的財務子系統的偵聽器實現與財務系統的通訊:
<bean id="orderEventListener" class="OrderEventListener" autowire="byName">
<propety name="financialService"><ref bean="financialService"/></property>
</bean>
這樣,我們與具體實現無關的事件廣播就做到了,聰明的朋友看到這里,肯定想到了攔截器方式不僅僅適用與事件廣播,還可以實現事務的統一管理,事實上Spring的事務管理就是這樣完成的,還可以實現權限的控制例如Acegi,簡直有點象萬能的膠水,呵呵。
從兩篇文章的逐步探討下,同一個機器,同一個虛擬機之內的數據通訊都可以實現了,那么異構系統和多虛擬機間的通訊又如何處理呢,于是ESB(企業服務總線)的概念就慢慢浮現出來了,不過這個不在本文探討的范疇了,也許在不久的將來,我會補上這一篇。
(全文完)