应用程序事件允许我们发送和接收特定事件,我们可以根据需要处理这些事件。事件用于在松散耦合的组件之间交换信息。由于发布者和订阅者之间没有直接耦合,因此可以在不影响发布者的情况下修改订阅者,反之亦然。
在Java中,通过java.util. EventObject来描述事件,通过java.util. EventListener来描述事件监听器。
// 用户实体
public class User {
private Long id;
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
public User(Long id) {this.id = id;}
}
// 用户事件
public class UserEvent extends EventObject {
public UserEvent(Object source) {super(source);}
}
// 邮件事件
public class EmailEvent extends UserEvent{
public EmailEvent(Object source) {super(source);}
}
// 用户监听器
public interface UserListener extends EventListener {
// 处理用户注册事件
void onRegister(UserEvent event);
}
// 邮件监听器
public class EmailListener implements UserListener {
@Override
public void onRegister(UserEvent event) {
if (event instanceof EmailEvent){
User user = (User) event.getSource();
System.out.println("给User Id为: " + user.getId() + "的用户发送邮件");
}
}
}
// 用户服务
public class UserService {
// 存放所有监听器
private final List<UserListener> listeners = new ArrayList<>();
// 添加监听器
public void addListener(UserListener userListener){
this.listeners.add(userListener);
}
// 注册用户并发布用户注册事件
public void register(User user){
System.out.println("注册新用户,Id为【" + user.getId() + "】");
publishEvent(new EmailEvent(user));
}
// 广播用户注册事件
private void publishEvent(UserEvent event){
for (UserListener listener : listeners) {
listener.onRegister(event);
}
}
public static void main(String[] args) {
UserService userService = new UserService();
User user = new User(1000L);
userService.addListener(new EmailListener());
userService.register(user);
}
}
// ==输出结果==
// 注册新用户,Id为【1000】
// 给User Id为: 1000的用户发送邮件
在Spring中,事件机制采用观察者模式进行具体实现,设计类图如下:
ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。
spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。
ApplicationEvent是Spring事件的顶层抽象类,代表事件本身,继承自JDK的EventObject。Spring提供了一些内置事件,如ContextClosedEvent、ContextStartedEvent、ContextRefreshedEvent、ContextStopedEvent等
事件类 | 描述 |
---|---|
ContextRefreshedEvent | ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用 |
ContextStartedEvent | 当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序 |
ContextStoppedEvent | 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作 |
ContextClosedEvent | 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。 |
RequestHandledEvent | 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。 |
ApplicationListener是Spring事件监听器顶层接口,所有的监听器都实现该接口,继承自JDK的EventListener。Spring提供了一些易扩展的接口,如SmartApplicationListener、GenericApplicationListener
ApplicationEventPublisher是Spring的事件发布接口,事件源通过该接口的publishEvent方法发布事件,所有的应用上下文都具备事件发布能力,因为ApplicationContext继承了该接口
ApplicationEventMulticaster是Spring事件机制中的事件广播器,它默认提供一个SimpleApplicationEventMulticaster实现,如果用户没有自定义广播器,则使用默认的(初始化逻辑见AbstractApplicationContext的refresh方法)。它通过父类AbstractApplicationEventMulticaster的getApplicationListeners方法从事件注册表中获取事件监听器,并且通过invokeListener方法执行监听器的具体逻辑。
默认的广播器是同步调用监听器的执行逻辑,但是可以通过为广播器配置Executor实现监听器的异步执行。
在Spring中通常是ApplicationContext本身担任监听器注册表的角色,在其子类AbstractApplicationContext中就聚合了事件广播器ApplicationEventMulticaster和事件监听器ApplicationListnener,并且提供注册监听器的addApplicationListnener方法。
当一个事件源产生事件时,它通过事件发布器ApplicationEventPublisher发布事件,然后事件广播器ApplicationEventMulticaster会去事件注册表ApplicationContext中找到事件监听器ApplicationListnener,并且逐个执行监听器的onApplicationEvent方法,从而完成事件监听器的逻辑。
事件:SpringApplicationEvent
SpringApplicationEvent是SpringBoot事件的顶层抽象类,且SpringBoot内置了7个事件:
上述7个事件在容器启动的合适阶段进行发布,发布顺序自上而下,可查看SpringApplication的run(String… args)方法,分别对应SpringApplicationRunListener的7个方法,源码如下:
// 该接口规定了SpringBoot的生命周期,会在各个生命周期广播响应的事件,调用实际的监听器
public interface SpringApplicationRunListener {
// 发布ApplicationStartingEvent
default void starting() {
}
// 发布ApplicationEnvironmentPreparedEvent
default void environmentPrepared(ConfigurableEnvironment environment) {
}
// 发布ApplicationContextInitializedEvent
default void contextPrepared(ConfigurableApplicationContext context) {
}
// 发布ApplicationPreparedEvent
default void contextLoaded(ConfigurableApplicationContext context) {
}
// 发布ApplicationStartedEvent
default void started(ConfigurableApplicationContext context) {
}
// 发布ApplicationReadyEvent
default void running(ConfigurableApplicationContext context) {
}
// 发布ApplicationFailedEvent
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
}
上述接口提供了唯一的实现类EventPublishingRunListener,该类聚合了SpringApplication和SimpleApplicationEventMulticaster,前4个事件的发布由广播器完成,后3个委托ApplicationContext完成发布,其实最终都是由广播器负责发布。
自定义事件监听一般包括事件源和、事件监听器
import org.springframework.context.ApplicationEvent;
public class TestEvent extends ApplicationEvent {
public TestEvent(Object obj) {
super(obj);
}
}
1.自定义监听器类+@Component
@Component
public class TestListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent event) {
System.out.println("监听到事件发生:"+event.getClass());
}
}
2.自定义监听器类+addListeners()
public class TestListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent event) {
System.out.println("监听到事件发生:"+event.getClass());
}
}
@SpringBootApplication
public class ScheduleApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(ScheduleApplication.class);
springApplication.addListeners(new TestListener());
springApplication.run(args);
}
}
3.自定义监听器类+配置文件
public class TestListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent event) {
System.out.println("监听到事件发生:"+event.getClass());
}
}
context:
listener:
classes: com.test.TestListener
4.@EventListener+@Component
@Component
public class TestListener {
@EventListener(value = TestEvent .class)
public void eventListener(TestEvent event) {
System.out.println("监听到事件发生:"+event.getClass());
}
}
@Component
public class ScheduleApplication {
@Autowired
private ApplicationContext context;
public void publish() {
context.publishEvent(new TestEvent(1));
}
}
ApplicationListener接口和SmartApplicationListener接口区别
实现ApplicationListener接口针对单一事件监听
实现SmartApplicationListener接口针对多种事件监听
SmartApplicationListener用法举例:
@Component
public class TestListener implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
boolean b = TestEvent.class.isAssignableFrom(eventType) || Test2Event.class.isAssignableFrom(eventType);
return b;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("监听到事件发生:"+event.getClass());
}
}
测试用例
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ListenerTest {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Test
public void test() {
TestEvent testEvent = new TestEvent("hello word");
applicationEventPublisher.publishEvent(testEvent);
}
}
接口
ServletContextListener
监听servletContext对象的创建以及销毁
执行时机:
contextInitialized(ServletContextEvent arg0) – 创建时执行
contextDestroyed(ServletContextEvent arg0) – 销毁时执行
ServletRequestListener
监听request对象的创建以及销毁
执行时机:
requestInitialized(ServletRequestEvent sre) – 创建时执行
requestDestroyed(ServletRequestEvent sre) – 销毁时执行
HttpSessionListener
监听session对象的创建以及销毁
执行时机:
sessionCreated(HttpSessionEvent se) – 创建时执行
sessionDestroyed(HttpSessionEvent se) – 销毁时执行
ServletContextAttributeListener
监听servletContext对象中属性的改变
执行时机:
attributeAdded(ServletContextAttributeEvent event) – 添加属性时执行
attributeReplaced(ServletContextAttributeEvent event) – 修改属性时执行
attributeRemoved(ServletContextAttributeEvent event) – 删除属性时执行
ServletRequestAttributeListener
监听request对象中属性的改变
attributeAdded(ServletRequestAttributeEvent srae) – 添加属性时执行
attributeReplaced(ServletRequestAttributeEvent srae) – 修改属性时执行
attributeRemoved(ServletRequestAttributeEvent srae) – 删除属性时执行
HttpSessionAttributeListener
监听session对象中属性的改变
attributeAdded(HttpSessionBindingEvent event) – 添加属性时执行
attributeReplaced(HttpSessionBindingEvent event) – 修改属性时执行
attributeRemoved(HttpSessionBindingEvent event) – 删除属性时执行
参考文章:
https://blog.csdn.net/JokerLJG/article/details/121541262
https://zhuanlan.zhihu.com/p/270596548