当我们在实现某些特定业务逻辑时,通常会通过发送事件的方式实现代码解耦,这也是观察者模式的一种体现。从spring 3.0.5为我们实现了用annotation实现event和eventListner。
一个事件包含:事件发布、监听、和事件源。在spring中我们可以通过ApplicationContext的publishEvent方法去发布事件;通过实现实现ApplicationListener接口来自定义自己的监听器;继承ApplicationEvent类来实现事件源。下面以一个实例来说明:
定义一个事件A事件源:
package cn.slimsmart.spring.demo.event;
import org.springframework.context.ApplicationEvent;
//A事件
public class AEvent extends ApplicationEvent{
private static final long serialVersionUID = 1L;
private String name = "AAAA";
public String getName() {
return name;
}
public AEvent(Object source) {
super(source);
}
}
监听事件A:
@Component
public class AEventListener implements ApplicationListener{
public void onApplicationEvent(ApplicationEvent event) {
System.err.println(this.getClass().getName());
if(event instanceof AEvent){
//处理事件A业务逻辑
}
System.out.println(event.getSource());
}
}
发布事件:
applicationContext.publishEvent(new AEvent("testA"));
从上面的监听器处理可以看出,需要通过event instanceof AEvent判断事件源来处理对于的业务逻辑,这样很不爽,当然有更好的方式。接口ApplicationListener支持泛型,可以通过泛型来判断处理的事件源。如下只处理BEvent源。
@Component
public class BEventListener implements ApplicationListener<BEvent>{
public void onApplicationEvent(BEvent bEvent) {
System.out.println("event name : "+bEvent.getName());
System.out.println(bEvent.getSource());
}
}
如果事件没要处理的监听器,就会被抛弃。
以上处理事件都是同步的,如果发布事件处的业务存在事务,监听器处理也会在相同的事务下。
如果是发送邮箱、短信等耗时操作,如何让事件异步处理呢?
1、全局异步配置
<task:executor id="executor" pool-size="3" queue-capacity="20" />
<bean id="applicationEventMulticaster"
class="org.springframework.context.event.SimpleApplicationEventMulticaster">
<property name="taskExecutor" ref="executor" />
bean>
通过注入taskExecutor来完成异步事件调用。不推荐全局配置。
2、@Aync注解来完成异步调用
spring3提供了@Aync注解来完成异步调用。不仅支持异步调用,还支持简单的任务调度。
<aop:aspectj-autoproxy proxy-target-class="true" />
<task:scheduler id="scheduler" pool-size="10" />
<task:executor id="executor" pool-size="10" />
<task:annotation-driven executor="executor" proxy-target-class="true" scheduler="scheduler" />
如上配置,在任何方法增加@Aync注解都会异步执行,通过executor完成异步处理。通过方法增加@Scheduled注解完成任务调度。
对于事件的处理可以onApplicationEvent方法上加@Aync支持异步。
@Aync注解的应用范围:
类:表示这个类中的所有方法都是异步的
方法:表示这个方法是异步的,如果类也注解了,则以这个方法的注解为准
上面的配置可以简化只配置:
默认会有缺省的executor。
注:在spring boot 开启异步配置在配置类中添加注解@EnableAsync 。