Spring 事件及监听模型

it2022-05-05  148

参考博客 https://blog.csdn.net/zrudong/article/details/78567473。

个人补充

事件及监听原理:观察者模式

观察者模式原理、优点。

Spring框架的事件监听接口

原理解析

从这个图中我们可以大致的了解Spring事件驱动中的各个组件是如何协同一起完成事件的触发和事件的执行。ApplicationListener作为Spring事件驱动中的监听器基类接口,要想实现一个由Spring驱动的事件监听,可以继承于该类;而ApplicationEventPublisher定义了事件的发布接口,Spring容器ApplicatonContext继承了该类,并实现了如何将是一个事件对象ApplicationEvent发布,并通知到事件监听器。先看分析下面几个比较重要的类:

ApplicationEvent: 事件对象,Spring事件驱动模型中的对象源,继承JDK EventObject,通过在发布事件时通过EventObject.source字段携带事件相关的数据。

ApplicationListener: 应用监听器,负责监听事件对象是否有发生变化,实现该接口并实现onApplicationEvent方法,完成事件发生变化时的逻辑处理

ApplicationEventPublisher: 事件发布器,定义了事件发布规范,只定义了接口,具体的实现交由其他类中实现。Spring提供了SimpleApplicationEventMulticaster实现了广播事件发布器。

理解Spring的事件模型可以从上的类图中,清晰地看到各个组件之间的合作关系,并将合作关系的共性抽象出来,对观察者模式做了抽象。  

下文我们会从事件驱动模型的各个构件出发分析Spring的事件驱动模型,包含事件对象、事件源(发布事件者)、事件监听器。

 

事件(事件对象)

Spring事件驱动模型中,承担事件对象的类是ApplicationEvent,集成JDK提供的事件对象EventObject.

此类为Spring事件中用于扩展的事件对象,所有需要使用事件驱动模型发布的事件都可以继承此类,并将事件对象Object source;传递给事件监听器使用,通过该source可以得到事件源,监听器拿到事件源后便可以处理自己的业务逻辑。

 

Spring自身的实现中,有很多地方用到了事件它自己定义的事件驱动模型。ApplicationContextEvent就是Spring容器事件的基类。

例如Spring中基于ApplicationContextEvent实现的事件如图所示: 

ContextStartedEvent:Spring Application容器启动后触发的事件。  ContextStopedEvent:Spring Application容器停止后触发的事件。  ContextClosedEvent:Spring Application容器关闭后触发的事件。  ContextRefreshedEvent:Spring Application容器初始化或者刷新完成后触发的事件。  

事件源-发布事件者

有了上面的事件对象后,如何发布事件对象呢?同样,Spring也提供了事件发布器,ApplicationContext继承了ApplicationEventPublisher,也就是说明Application有了事件发布的功能。

 

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean { // 省略其他代码 public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster"; @Override public void publishEvent(ApplicationEvent event) { publishEvent(event, null); } @Override public void publishEvent(Object event) { publishEvent(event, null); } protected void publishEvent(Object event, ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } // Decorate event as an ApplicationEvent if necessary ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<Object>(this, event); if (eventType == null) { eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass()); } } // Multicast right now if possible - or lazily once the multicaster is initialized if (this.earlyApplicationEvents != null) { this.earlyApplicationEvents.add(applicationEvent); } else { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } // Publish event via parent context as well... if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }

 

Spring事件发布流程

注册监听器到Spring框架

监听器在内部被谁以及如何存储和管理?

在生命周期的各个阶段,发布指定类型的事件

各周期发布的事件列表,以及对应的监听器?

通过谁发布事件?

从注册的监听器列表中,查找监听当前事件的监听器

如何查找?

监听器接收并处理相关事件

 

Spring生命周期

Spring在生命周期的各阶段都发布哪些事件,以及对应的监听器

自定义事件及监听器,并加入到Spring框架

 


最新回复(0)