基于SPRING的事件处理其实很简单,初学者不必一开始就担心搞不懂,本文先是介绍完全基于SPRING的事件监听实现(熟识Spring事件监听的朋友应该跳过第一节),然后依葫芦画瓢自已做一个性能更好事件监听小框架,最后在回贴中加入了注解版。
为何要使用事件监听,而不是直接调用?打个比方,在系统删除一个用户时,需要把用户的其他信息和行为记录一起删除,此时最容易想到的是:删除用户时,调用其他Service类接口删除与之相关的信息和用户行为记录,但是用户是一个基础模块,随着系统模块不断增加,会有越来越多的模块与之关联,按以上方案,每增加一个与用户相关的模块,那么删除用户时就要把这个模块的信息也一起删除,这样用户这个模块就与这些业务模块偶合在一起了,只要系统不断的增加或减少模块,用户模块就永远都改不完。(以上逻辑仅为说明问题)
如果采用事件监听,那么在删除一个用户时,发布一事件就完事了,所有相关的模块监听此事件,在事件处理中删除本模块对应的数据,那么用户模块也不会与这些模块有任何偶合了。
好,回到主题,
1、完全基于SPRING的事件监听与处理:
首先,SERVICE总接口类继承org.springframework.context.ApplicationListener接口,并且在SERVICE的抽象类中实现此接口的方法,SERVICE总接口代码:
- import org.springframework.context.ApplicationListener;
- /**
- * 业务层顶层接口
- */
- public interface IBaseService extends ApplicationListener{
- }
SERVICE抽象类代码,所有具体业务类皆继承此抽象业务类
- import org.springframework.context.ApplicationEvent;
- /**
- * 实现顶层接口的抽象类
- */
- public abstract class AbstractBaseService implements IBaseService {
- /**
- * 此方法不允许重写,要监听事件,重写onBaseEvent方法
- */
- public final void onApplicationEvent(ApplicationEvent event) {
- if (event instanceof BaseEvent) {
- onBaseEvent((BaseEvent) event);
- }
- }
- /**
- * 要监听事件就重写此方法
- */
- protected void onBaseEvent(BaseEvent event) {
- }
- /**
- * 发布事件
- */
- protected final void publishEvent(BaseEvent event) {
- //取得SPRING容器并发布事件
- org.springframework.web.context.ContextLoader.getCurrentWebApplicationContext().publishEvent(event);
- }
- }
BaseEvent类是我自定义的一个类,各业务模块要发布事件,首先定义自已的EVENT类,继承BaseEvent。BaseEvent类代码
- import org.springframework.context.ApplicationEvent;
- public class BaseEvent extends ApplicationEvent {
- public BaseEvent(Object source) {
- super(source);
- }
- }
用户业务类UserSerivceImpl删除一个用户时,需要发布事件,所以要先定义一个UserDeleteEvent事件类
- import com.esc.permission.model.User;
- public class UserDeleteEvent extends BaseEvent {
- public UserDeleteEvent(User user){
- super(user);
- }
- public User getUser(){
- return (User) super.getSource();
- }
- }
下面是UserSerivceImpl类删除用户的方法模拟
- public void deleteUser(String id){
- //先发布删除事件
- publishEvent(new UserDeleteEvent(new User(id)));
- //再把用户删除
- userDao.deleteUser(id);
- }
假如有一个OtherServiceImpl业务类需要接收用户删除事件并做一些处理,
- public class OtherServiceImpl extends AbstractBaseService {
- private IBaseDAO otherDao;
- /**
- * 重写父类的方法,处理用户删除事件
- */
- protected void onBaseEvent(BaseEvent baseEvent){
- if(baseEvent instanceof UserDeleteEvent){//如果是用户删除事件
- otherDao.deleteOtherData(((User)baseEvent.getSource()).getId());
- }
- }
- }
到此,所有逻辑就完了,用户业务类中根本不需要知道谁将会处理此事件,所以完全与其它模块解偶了。
这里用了一个偷懒的方法,那就是在业务类的顶层接口IBaseService中实现了ApplicationListener接口,这样其实所有具体业务类都参与了所有事件的处理,即使是那些根本不需要监听事件的业务类。对于所有根本不需要监听事件的业务类,事件发生时就调用其父类空方法onBaseEvent,这里有一点性能浪费,如果改进?不要在顶层接口IBaseService中实现ApplicationListener接口,而是在具体的需要监听事件的业务类中实现此接口,但是这样还是有一点缺陷,那就是此具体业务类还是会监听到它不关心的事件,不论是用户删除事件还是用户修改事件,没办法,有得必有失,想要方便,肯定会有所牺牲。