文章连接:liuyueyi.github.io/hexblog/hex…java
关于事件的发起与相应,在客户端的交互中可算是很是频繁的事情了,关于事件的发布订阅,在Java生态中,EventBus可谓是很是有名了,而Spring也提供了事件机制,本文则主要介绍后端如何在Spring的环境中,使用事件机制git
主要借助org.springframework.context.ApplicationEventPublisher#publishEvent(org.springframework.context.ApplicationEvent)
来发布事件,而接受方,则直接在处理的方法上,添加 @@EventListener
注解便可github
发布一个事件,因此第一件事就是要定义一个事件,对Spring而言,要求自定义的事件继承自ApplicationEvent
类, 一个简单的demo以下spring
public class NotifyEvent extends ApplicationEvent {
@Getter
private String msg;
public NotifyEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
}
复制代码
发布时间则比较简单,直接拿到ApplicationContext实例,执行publish方法便可,以下面给出一个简单的发布类后端
@Component
public class NotifyPublisher implements ApplicationContextAware {
private ApplicationContext apc;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.apc = applicationContext;
}
// 发布一个消息
public void publishEvent(int status, String msg) {
if (status == 0) {
apc.publishEvent(new NotifyEvent(this, msg));
} else {
apc.publishEvent(new NewNotifyEvent(this, msg, ((int) System.currentTimeMillis() / 1000)));
}
}
}
复制代码
在方法上添加注解便可,以下app
@Component
public class NotifyQueueListener {
@EventListener
public void consumerA(NotifyEvent notifyEvent) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg());
}
@EventListener
public void consumerB(NewNotifyEvent notifyEvent) {
System.out.println("B: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg());
}
@EventListener
public void consumerC(NotifyEvent notifyEvent) {
System.out.println("C: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg());
}
}
复制代码
上面给出了使用的姿式,看起来并不复杂,也比较容易使用,可是一个问题须要在使用以前弄明白了,发布事件和监听器是怎么关联起来的呢?异步
那么若是发布者,推送的是一个NotifyEvent
类型的事件,那么接收者是怎样的呢?ide
测试用例以下:学习
NewNotifyEvent
继承自上面的NotifyEvent
测试
public class NewNotifyEvent extends NotifyEvent {
@Getter
private int version;
public NewNotifyEvent(Object source, String msg) {
super(source, msg);
}
public NewNotifyEvent(Object source, String msg, int version) {
super(source, msg);
this.version = version;
}
}
复制代码
而后借助上面的消息发布者发送一个消息
@Test
public void testPublishEvent() throws InterruptedException {
notifyPublisher.publishEvent(1, "新的发布事件! NewNotify");
System.out.println("---------");
notifyPublisher.publishEvent(0, "旧的发布事件! Notify");
}
复制代码
输出结果以下,对于NewNotifyEvent, 参数类型为NotifyEvent的consumerA, consumerC均可以接收到
A: main | 新的发布事件! NewNotify
C: main | 新的发布事件! NewNotify
B: main | 新的发布事件! NewNotify
---------
A: main | 旧的发布事件! Notify
C: main | 旧的发布事件! Notify
复制代码
上面消息处理是串行的,那么前后顺序怎么肯定? (下面的答案不肯定,有待深刻源码验证!!!)
对于异步消费,即在消费者方法上添加一个@Async
注解,并须要在配置文件中,开启异步支持
@Async
@EventListener
public void processNewNotifyEvent(NewNotifyEvent newNotifyEvent) {
System.out.println("new notifyevent: " + newNotifyEvent.getMsg() + " : " + newNotifyEvent.getVersion());
}
复制代码
配置支持
@Configuration
@EnableAsync
public class AysncListenerConfig implements AsyncConfigurer {
/** * 获取异步线程池执行对象 * * @return */
@Override
public Executor getAsyncExecutor() {
return new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(),
new DefaultThreadFactory("test"), new ThreadPoolExecutor.CallerRunsPolicy());
}
}
复制代码
一灰灰的我的博客,记录全部学习和工做中的博文,欢迎你们前去逛逛
尽信书则不如,已上内容,纯属一家之言,因我的能力有限,不免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激