共计 2725 个字符,预计需要花费 7 分钟才能阅读完成。
借助 Spring 能够非常简单的实现事件监听机制,本文简略介绍上面向接口与注解监听的两种姿态
【SpringBoot 根底系列】事件机制的两种生产姿态
<!– more –>
I. 我的项目环境
本我的项目借助 SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
进行开发
为了前面的公布事件验证,起一个 web 服务
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
II. 事件机制
1. 事件对象
在 Spring 中,所有的事件须要继承自 ApplicationEvent
,一个最根底的MsgEvent
如下
public class MsgEvent extends ApplicationEvent {
private String msg;
/**
* Create a new {@code ApplicationEvent}.
*
* @param source the object on which the event initially occurred or with
* which the event is associated (never {@code null})
*/
public MsgEvent(Object source, String msg) {super(source);
this.msg = msg;
}
@Override
public String toString() {
return "MsgEvent{" +
"msg='" + msg + '\'' +
'}';
}
}
2. 接口方式生产
生产事件有两种形式,接口的申明,次要是实现 ApplicationListener
接口;留神须要将 listener 申明为 Spring 的 bean 对象
@Service
public class MsgEventListener implements ApplicationListener<MsgEvent> {
@Override
public void onApplicationEvent(MsgEvent event) {System.out.println("receive msg event:" + event);
}
}
3. 注解形式生产
实现接口须要新建实现类,更简略的办法是间接在生产办法上加一个注解@EventListener
@EventListener(MsgEvent.class)
public void consumer(MsgEvent msgEvent) {System.out.println("receive msg by @anno:" + msgEvent);
}
这个注解,反对依据 Event 参数类型进行匹配,即下面的实例中,办法上间接加 @EventListener
不指定圆括号外部的也没关系
4. 公布事件
后面是生产事件,生产的前提是有事件产生,在 Spring 中,公布事件次要须要借助 ApplicationContext
来实现
@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
@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
输入日志:
receive msg by @anno: MsgEvent{msg='一灰灰 blog'}
receive msg event: MsgEvent{msg='一灰灰 blog'}
下面这个测试两种生产形式都能够胜利,然而,在实测的过程中发现一种 case,注解生产形式不失效,测试姿态如下
@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. 我的项目
- 工程:https://github.com/liuyueyi/spring-boot-demo
- 源码:https://github.com/liuyueyi/spring-boot-demo/blob/master/spring-boot/012-context-listener/
1. 一灰灰 Blog
尽信书则不如,以上内容,纯属一家之言,因集体能力无限,不免有疏漏和谬误之处,如发现 bug 或者有更好的倡议,欢送批评指正,不吝感谢
上面一灰灰的集体博客,记录所有学习和工作中的博文,欢送大家前去逛逛
- 一灰灰 Blog 集体博客 https://blog.hhui.top
- 一灰灰 Blog-Spring 专题博客 http://spring.hhui.top
- 微信公众号: 一灰灰 blog