Spring - 事件驱动模型
Spring - 事件驱动模型
Spring 事件驱动模型也是观察者模式很经典的应用。
一、Spring 中观察者模式的四个角色
1. 事件 - ApplicationEvent
ApplicationEvent 是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过 source 得到事件源。
Spring 也为我们提供了很多内置事件,ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent。如下图:
2. 事件监听 - ApplicationListener
ApplicationListener,也就是观察者,继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent。当监听的事件发生后该方法会被执行。如下图:
3. 事件源 - ApplicationContext
ApplicationContext 是 Spring 中的核心容器,在事件监听中 ApplicationContext 可以作为事件的发布者,也就是事件源。因为 ApplicationContext 继承自 ApplicationEventPublisher。如下图:
在 ApplicationEventPublisher 中定义了事件发布的方法:publishEvent(Object event)
1 @FunctionalInterface 2 public interface ApplicationEventPublisher { 3 4 default void publishEvent(ApplicationEvent event) { 5 publishEvent((Object) event); 6 } 7 8 void publishEvent(Object event); 9 10 }
4. 事件管理 - ApplicationEventMulticaster
用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 ApplicationContext 发布的 Event 广播给它的监听器列表。如下图:
定义事件:
1 public class MyEvent extends ApplicationEvent { 2 public MyEvent(Object source) { 3 super(source); 4 System.out.println("my Event"); 5 } 6 }
实现事件监听器:
1 @Component 2 class MyListenerA implements ApplicationListener<MyEvent> { 3 public void onApplicationEvent(MyEvent AyEvent) { 4 System.out.println("ListenerA received"); 5 } 6 } 7 8 @Component 9 class MyListenerB implements ApplicationListener<MyEvent> { 10 public void onApplicationEvent(MyEvent AyEvent) { 11 System.out.println("ListenerB received"); 12 } 13 }
除了上面这种方式,还可以使用注解的方式来自定义事件监听器,比如:
1 // 自定义事件监听器 2 @Component 3 class CustomEventListener { 4 @EventListener 5 public void handleCustomStartupEvent(CustomStartupEvent event) { 6 System.out.println("Custom startup event received from: " + event.getSource()); 7 } 8 }
说明:使用@EventListener时,不需要实现onApplicationEvent方法。Spring 会通过反射调用这个方法来处理事件。这种方式使得代码更加简洁,易于阅读。
事件发布者:
1 @Component 2 public class MyPublisher implements ApplicationContextAware { 3 private ApplicationContext applicationContext; 4 5 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 6 this.applicationContext = applicationContext; 7 } 8 9 public void publishEvent(ApplicationEvent event){ 10 System.out.println("publish event"); 11 applicationContext.publishEvent(event); 12 } 13 }
测试,先用注解方式将 MyPublisher 注入 Spring
1 @Configuration 2 @ComponentScan 3 public class AppConfig { 4 5 @Bean(name = "myPublisher") 6 public MyPublisher myPublisher(){ 7 return new MyPublisher(); 8 } 9 }
客户端测试代码:
1 public class Client { 2 3 @Test 4 public void main() { 5 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); 6 MyPublisher myPublisher = (MyPublisher) context.getBean("myPublisher"); 7 myPublisher.publishEvent(new MyEvent(this)); 8 } 9 } 10 11 12 //运行结果 13 my Event 14 publish event 15 ListenerA received 16 ListenerB received
二、显示遍历观察者的问题
在 Spring 的事件监听机制中,事件的发布和监听机制通常并不直接涉及到在主题对象中显式地遍历观察者(或监听器)。相反,它们利用了 Spring 的应用上下文(ApplicationContext)和事件发布机制来管理事件的发送和监听。
1. SimpleApplicationEventMulticaster
Spring 使用 SimpleApplicationEventMulticaster 作为事件广播器,它会负责将事件分发给所有注册的监听器
SimpleApplicationEventMulticaster 部分代码如下:
1 public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { 2 3 //... 4 5 @Override 6 public void multicastEvent(ApplicationEvent event) { 7 multicastEvent(event, resolveDefaultEventType(event)); 8 } 9 10 @Override 11 public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { 12 ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); 13 Executor executor = getTaskExecutor(); 14 for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { 15 if (executor != null) { 16 executor.execute(() -> invokeListener(listener, event)); 17 } 18 else { 19 invokeListener(listener, event); 20 } 21 } 22 } 23 }
从invokeListener方法追踪到后面的代码,我们看到最终执行的是listener.onApplicationEvent(event);
其实也就是执行ApplicationListener实现类的onApplicationEvent方法,里面的内容是监听器在事件发生时执行的特定逻辑。
在 Spring中,事件监听机制通过 ApplicationEventPublisher 和 ApplicationListener 实现了事件的发布和监听。
事件的分发由 Spring 内部的事件广播器(如 SimpleApplicationEventMulticaster)处理,避免了在主题对象中显式地遍历观察者。
这种机制的好处包括:
- 解耦:事件发布者和事件监听器之间解耦,提高了系统的灵活性和可维护性。
- 集中管理:事件的注册和分发由 Spring 容器管理,简化了事件处理逻辑。
- 扩展性:可以方便地添加或移除监听器,而不需要修改事件发布的代码。