Spring提供了事件机制,其本质是JDK提供的事件机制的应用,利用的是观察者设计模式,具体请看设计模式之观察者模式(Observer Pattern)。
主要成员:
ApplicationEvent:发布事件消息载体
ApplicationListener:监听器
@EventListener:注解事件监听器
代码示例:
监听器
@Component
public class MyEventListen{
/**
* 异步和发布方法在同一个事务中
*/
@Async
@TransactionalEventListener(MyEvent.class)
public void myEvent(MyEvent event) {
System.out.println("线程名称"+Thread.currentThread().getName()+"监听到MyEvent消息了");
System.out.println("监听到了spring消息,消息体:"+ JSONObject.toJSONString(event.getSource()));
}
/**
* 同步监听
* @param event
*/
@EventListener(OtherEvent.class)
public void onApplicationEvent(OtherEvent event) {
System.out.println("线程名称"+Thread.currentThread().getName()+"监听到OtherEvent消息了");
System.out.println("监听到了spring消息,消息体:"+ JSONObject.toJSONString(event.getSource()));
}
}
事件消息载体示例
public class MyEvent extends ApplicationEvent {
public MyEvent(EventDTO source) {
super(source);
}
}
@Data
@EqualsAndHashCode(callSuper = false)
public class EventDTO {
private String tager;
private String msg;
}
public class OtherEvent extends ApplicationEvent {
public OtherEvent(OtherDto dto) {
super(dto);
}
@Data
@EqualsAndHashCode(callSuper = false)
public static class OtherDto{
/**请求头*/
private String title;
/**消息*/
private String msg;
}
}
发布事件
@Resource
private ApplicationContext applicationContext;
public void publishMyEvent() throws InterruptedException {
System.out.println("线程名称"+Thread.currentThread().getName()+"发布消息");
EventDTO eventDTO = new EventDTO();
eventDTO.setMsg("spring event消息");
eventDTO.setTager("place");
applicationContext.publishEvent(new MyEvent(eventDTO));
Thread.sleep(1000);
System.out.println("线程名称"+Thread.currentThread().getName()+"跑完了");
}
public void publishOtherEvent() throws InterruptedException {
System.out.println("线程名称"+Thread.currentThread().getName()+"发布消息");
OtherEvent.OtherDto eventDTO = new OtherEvent.OtherDto();
eventDTO.setMsg("spring event消息");
eventDTO.setTitle("other");
applicationContext.publishEvent(new OtherEvent(eventDTO));
Thread.sleep(1000);
System.out.println("线程名称"+Thread.currentThread().getName()+"跑完了");
}
测试类
@Resource
private MyEventPublish eventPublish;
@Test
public void testPublish() throws InterruptedException {
eventPublish.publishMyEvent();
eventPublish.publishOtherEvent();
}
输出结果
线程名称main发布消息
线程名称task-1监听到MyEvent消息了
监听到了spring消息,消息体:{"msg":"spring event消息","tager":"place"}
线程名称main跑完了
线程名称main发布消息
线程名称main监听到OtherEvent消息了
监听到了spring消息,消息体:{"msg":"spring event消息","title":"other"}
线程名称main跑完了
如果加了@Async注解,发现监听器和发布事件的还是同一个线程,则检查下是否启动类中没有加 @EnableAsync 这个注解