Spring事件
在spring容器中是通过ApplicationEvent
类和ApplicationListener
接口来处理事件的。如果某个bean实现了ApplicationListener
接口并被部署到容器中,那么每次对应的ApplicationEvent
被发布到容器中时,都会通知该bean,在设计模式中这个叫观察者模式。
spring的事件默认是同步的,即调用publisEvent()
方法发布事件后, 它会处于阻塞状态,直到onApplicationEvent
接收到事件并处理完返回之后才会继续往下执行,这种单线程同步的好处是可以进行事务管理。
Spring标准事件
Event | 说明 |
---|---|
ContextRefreshedEvent | 当容器被实例化或refreshed时发布.如调用refresh()方法, 此处的实例化是指所有的bean都已被加载,后置处理器都被激活,所有单例bean都已被实例化, 所有的容器对象都已准备好可使用. 如果容器支持热重载,则refresh可以被触发多次(XmlWebApplicatonContext支持热刷新,而GenericApplicationContext则不支持) |
ContextStartedEvent | 当容器启动时发布,即调用start()方法, 已启用意味着所有的Lifecycle bean都已显式接收到了start信号 |
ContextStoppedEvent | 当容器停止时发布,即调用stop()方法, 即所有的Lifecycle bean都已显式接收到了stop信号 , 关闭的容器可以通过start()方法重启 |
ContextClosedEvent | 当容器关闭时发布,即调用close方法, 关闭意味着所有的单例bean都已被销毁.关闭的容器不能被重启或refresh |
RequestHandledEvent | 这只在使用spring的DispatcherServlet时有效,当一个请求被处理完成时发布 |
代码实现
实现Spring标准事件只需要实现ApplicationListener并重写onApplicationEvent方法即可
@Slf4j
@Component
public class ContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
log.info("监听到ContextRefreshedEvent {}", event);
}
}
结果
2020-09-22 13:02:18.481 INFO 10600 --- [ main] c.m.e.e.ContextRefreshedEventListener : 监听到ContextRefreshedEvent org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@35cabb2a, started on Tue Sep 22 13:02:17 CST 2020]
Spring自定义事件
代码实现
定义事件
定义通知事件
public class NotifyEvent extends ApplicationEvent {
private final String address;
private final String content;
/**
* 构造方法中构建事件内容
*
* @param source
* @param address
* @param content
*/
public NotifyEvent(Object source, String address, String content) {
super(source);
this.address = address;
this.content = content;
}
public String getAddress() {
return address;
}
public String getContent() {
return content;
}
@Override
public String toString() {
return "BlackListEvent{" +
"address='" + address + '\'' +
", content='" + content + '\'' +
'}';
}
}
定义监听器
邮件监听器
@Slf4j
@Component
public class MailEventListener implements ApplicationListener<NotifyEvent> {
private String notificationAddress;
/**
* 对接收到的事件进行处理
*
* @param event
*/
@Override
public void onApplicationEvent(NotifyEvent event) {
log.info("发送邮件 {}", event);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("发送邮件 {}完成", event);
}
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public String getNotificationAddress() {
return this.notificationAddress;
}
}
短信监听器
@Slf4j
@Component
public class SmsEventListener implements ApplicationListener<NotifyEvent> {
private String notificationAddress;
/**
* 对接收到的事件进行处理
*
* @param event
*/
@Override
public void onApplicationEvent(NotifyEvent event) {
log.info("发送短信 {}", event);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("发送短信 {}完成", event);
}
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public String getNotificationAddress() {
return this.notificationAddress;
}
}
在Spring中发布事件
@Slf4j
@Service
public class NotifyService implements ApplicationEventPublisherAware {
@Autowired
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public void notify(String address, String content) {
log.info("发布事件");
NotifyEvent event = new NotifyEvent(this, address, content);
publisher.publishEvent(event);
}
}
结果
2020-09-22 13:47:46.159 INFO 12844 --- [nio-9000-exec-2] com.mantis.event.event.NotifyService : 发布事件
2020-09-22 13:47:46.160 INFO 12844 --- [nio-9000-exec-2] c.mantis.event.event.MailEventListener : 发送邮件 BlackListEvent{address='D', content=''}
2020-09-22 13:47:51.160 INFO 12844 --- [nio-9000-exec-2] c.mantis.event.event.MailEventListener : 发送邮件 BlackListEvent{address='D', content=''}完成
2020-09-22 13:47:51.160 INFO 12844 --- [nio-9000-exec-2] com.mantis.event.event.SmsEventListener : 发送短信 BlackListEvent{address='D', content=''}
2020-09-22 13:47:56.161 INFO 12844 --- [nio-9000-exec-2] com.mantis.event.event.SmsEventListener : 发送短信 BlackListEvent{address='D', content=''}完成
总结
Spring使用事件通知机制方便系统的解耦,比如发送邮件功能,如果按照调用第三方服务的写法,就需要定义一个邮件发送接口,由后续开发者实现功能,而有了监听事件,一个事件可以配置多个监听,方便系统进行解耦。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。