借助Spring可以非常简单的实现事件监听机制,本文简单介绍下面向接口与注解监听的两种姿势
I. 项目环境 本项目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA进行开发
为了后面的发布事件验证,起一个web服务
1 2 3 4 5 6 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies >
II. 事件机制 1. 事件对象 在Spring中,所有的事件需要继承自ApplicationEvent,一个最基础的MsgEvent如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class MsgEvent extends ApplicationEvent { private String msg; public MsgEvent (Object source, String msg) { super (source); this .msg = msg; } @Override public String toString () { return "MsgEvent{" + "msg='" + msg + '\'' + '}' ; } }
2. 接口方式消费 消费事件有两种方式,接口的声明,主要是实现ApplicationListener接口;注意需要将listener声明为Spring的bean对象
1 2 3 4 5 6 7 @Service public class MsgEventListener implements ApplicationListener <MsgEvent > { @Override public void onApplicationEvent (MsgEvent event) { System.out.println("receive msg event: " + event); } }
3. 注解方式消费 实现接口需要新建实现类,更简单的方法是直接在消费方法上加一个注解@EventListener
1 2 3 4 @EventListener (MsgEvent.class)public void consumer (MsgEvent msgEvent) { System.out.println("receive msg by @anno: " + msgEvent); }
这个注解,支持根据Event参数类型进行匹配,即上面的实例中,方法上直接加@EventListener不指定圆括号内部的也没关系
4. 发布事件 前面是消费事件,消费的前提是有事件产生,在Spring中,发布事件主要需要借助ApplicationContext来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 @Service public class MsgPublisher implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext (ApplicationContext applicationContext) throws BeansException { this .applicationContext = applicationContext; } public void publish (String msg) { applicationContext.publishEvent(new MsgEvent(this , msg)); } }
5. 测试 一个简单的测试demo
1 2 3 4 5 6 7 8 9 10 11 @RestController public class IndexController { @Autowired private MsgPublisher msgPublisher; @GetMapping (path = "pub" ) public String publish (String msg) { msgPublisher.publish(msg); return "ok" ; } }
访问: curl http://localhost:8082/pub?msg=一灰灰blog
输出日志:
1 2 receive msg by @anno: MsgEvent{msg='一灰灰blog'} receive msg event: MsgEvent{msg='一灰灰blog'}
上面这个测试两种消费方式都可以成功,但是,在实测的过程中发现一种case,注解消费方式不生效,测试姿势如下
1 2 3 4 5 6 7 8 9 10 11 @SpringBootApplication public class Application { public Application (MsgPublisher msgPublisher) { msgPublisher.publish("一灰灰blog" ); } public static void main (String[] args) { SpringApplication.run(Application.class); } }
直接在启动类的构造方法中发布事件,发现接口方式可以接收事件,但是注解方式不生效,why?
在stockoverstack上有个相似的问题 https://stackoverflow.com/questions/38487474/springboot-eventlistener-dont-receive-events ,这里主要提了一个观点
那么是这个原因么? 静待下次源码分析
II. 其他 0. 项目
1. 一灰灰Blog 尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
打赏
如果觉得我的文章对您有帮助,请随意打赏。
微信打赏
支付宝打赏