在上一篇文章里,我们使用了基于事件传递的机制来对企业应用的子系统进行解耦,但是由于需要强制地继承或者实现一个广播事件的接口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(企业服务总线)的概念就慢慢浮现出来了,不过这个不在本文探讨的范畴了,也许在不久的将来,我会补上这一篇。
(全文完)