spring事件是一个监听者模式,监听者模式包含了一个监听者Listener与之对应的事件Event,还有一个事件发布者EventPublish,过程就是EventPublish发布一个事件,被监听者捕获到,然后执行事件相应的方法。
1、定义事件,继承ApplicationEvent ,写构造函数。
@Data
public class MessageEvent extends ApplicationEvent {
private long fromUserId;
private long toUserId;
private long postId;
private int event; //事件类型
public MessageEvent(Object source,int event) {
super(source);
this.event = event;
}
}
2、定义监听者,实现ApplicationListener接口,重写onApplicationEvent方法。
@Slf4j
@Component
public class MessageEventHandle implements ApplicationListener<MessageEvent> { //泛型代表着要监听的事件
@Override
public void onApplicationEvent(MessageEvent messageEvent) {
//TODO 业务处理
//代表着不同的事件
if (messageEvent.getEvent() == Consts.MESSAGE_EVENT_COLLECT_POST) {
log.info("---------------> 收藏" + messageEvent.toString());
} else if (messageEvent.getEvent() == Consts.MESSAGE_EVENT_FAVOR_POST) {
log.info("---------------> 喜欢" + messageEvent.toString());
}
}
}
public class Consts {
/**
* 喜欢
*/
public static final int MESSAGE_EVENT_FAVOR_POST = 0;
/**
* 收藏
*/
public static final int MESSAGE_EVENT_COLLECT_POST = 1;
}
3、测试
@Autowired
ApplicationContext applicationContext;
@GetMapping("/test")
public User selectUser() {
MessageEvent messageEvent = new MessageEvent(this, Consts.MESSAGE_EVENT_COLLECT_POST);
messageEvent.setPostId(1L);
messageEvent.setFromUserId(2L);
messageEvent.setToUserId(3L);
//发布事件
applicationContext.publishEvent(messageEvent);
User user = userService.getById(1L);
log.info("---------> " + user.toString());
return user;
}
4、结果
另外要注意的一点是,发布事件的方法与事件处理是同步的,在service中有注册 @Transactional的情况下,listener中的do something和service中的是在同一个tansaction下。
例如:我们在监听方法中睡眠1s
@Override
public void onApplicationEvent(MessageEvent messageEvent) {
//TODO 业务处理
//睡眠1s
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//代表着不同的事件
if (messageEvent.getEvent() == Consts.MESSAGE_EVENT_COLLECT_POST) {
log.info("---------------> 收藏" + messageEvent.toString());
} else if (messageEvent.getEvent() == Consts.MESSAGE_EVENT_FAVOR_POST) {
log.info("---------------> 喜欢" + messageEvent.toString());
}
}
输出顺序依然相同。
这个时候只要再开一个线程处理事件。再springboot中很简单就可以实现。
1、在监听者方法上了加入 @Async注解。
2、在application上开启 @EnableAsync
/**
* @Async 表示异步调用
*/
@Async
@Override
public void onApplicationEvent(MessageEvent messageEvent) {
//TODO 业务处理
//睡眠1s
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//代表着不同的事件
if (messageEvent.getEvent() == Consts.MESSAGE_EVENT_COLLECT_POST) {
log.info("---------------> 收藏" + messageEvent.toString());
} else if (messageEvent.getEvent() == Consts.MESSAGE_EVENT_FAVOR_POST) {
log.info("---------------> 喜欢" + messageEvent.toString());
}
}
@EnableAsync
@MapperScan("com.example.mapper")
@SpringBootApplication
public class SpringLearn3Application {
public static void main(String[] args) {
SpringApplication.run(SpringLearn3Application.class, args);
}
}
结果:
如果不是springboot,可以参考https://www.jianshu.com/p/21984b08875c