Spring的事件通知机制是一项很有用的功能,使用事件机制我们可以将相互耦合的代码解耦,从而方便功能的修改与添加。
举个栗子:下单成功给用户送积分。这里介绍两种实现方式:
spring的event事件机制
首先定义事件模型OrderEvent:
public class OrderEvent extends ApplicationEvent {
private Long orderId;
public OrderEvent(Object source) {
super(source);
}
public OrderEvent(Object source, Long orderId) {
super(source);
this.orderId = orderId;
}
public Long getOrderId() {
return orderId;
}
public void setOrderId(Long orderId) {
this.orderId = orderId;
}
}
然后定义事件监听器OrderListener:
@Component
public class OrderListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent orderEvent) {
System.out.println("OrderListener监听到订单消息,订单ID:" + orderEvent.getOrderId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
最后定义事件发布器OrderPubilsher:
@Component
public class OrderPubilsher {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public void publish(long orderId){
OrderEvent event = new OrderEvent(this,orderId);
applicationEventPublisher.publishEvent(event);
System.out.println("订单完成!");
}
}
这里的事件监听器默认是同步阻塞的,如果要定义一个异步监听器也很简单,配置一个异步的线程池。
@Async
@Component
public class OrderListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent orderEvent) {
System.out.println("OrderListener监听到订单消息,订单ID:" + orderEvent.getOrderId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
定义一个线程池,开启异步线程注解:
@EnableAsync
@Configuration
public class TaskPoolConfig {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); //线程池创建时候初始化的线程数
executor.setMaxPoolSize(20); //线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setQueueCapacity(200); //用来缓冲执行任务的队列
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
//用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean,这样这些异步任务的销毁就会先于Redis线程池的销毁
executor.setWaitForTasksToCompleteOnShutdown(true);
//该方法用来设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
executor.setAwaitTerminationSeconds(60);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
测试方法,这里就贴了。
异常处理
Spring 4.1对异步调用提供了AsyncResult及SuccessCallback、FailureCallback、和异常处理的支持;对事件调度也提供了相应的异常处理器。
1、事件调度异常处理器
1.1、定义异常处理器:
public class MyErrorHandler implements ErrorHandler {
@Override