spring5.x-listener principle and source code implementation

Above: spring5.x-solve circular dependency analysis


Articles in this series:

                spring5.x-solve circular dependency analysis

                spring5.x-IOC module source code learning

                Spring5.x introduction and matching spring source code reading environment


basic knowledge

    The Spring framework's event mechanism allows objects to listen for and respond to specific events when they occur. The principle of Spring listener mainly involves the following core concepts:

  1. Events: Events in Spring refer to various actions or state changes that occur in the application, such as object creation, method invocation, exception throwing, etc.

  2. Event source: The event source is the object that triggers the event, which usually triggers the event through the publisher (Publisher).

  3. Event listener: An event listener is an interface that defines methods for listening and processing specific events. It can be registered with the application context to be called when an event occurs.

  4. Event publisher (broadcaster): The event publisher is responsible for managing the publishing of events and the registration of event listeners. In Spring, ApplicationContext is the implementation of an event publisher, which can publish events and pass them to registered event listeners.

The workflow of Spring listener is as follows:

  1. Create an event object: When an event occurs, you first need to create an object representing the event.

  2. Publish an event: The event object is passed to the event publisher (ApplicationContext), and the publisher distributes the event to the corresponding listener by traversing the registered listener list.

  3. Execution of the listener: After the listener receives the event, it calls the event processing method for processing. The number and order of listeners is determined by the registration order, and the event processing method can execute arbitrary business logic.

The principle of Spring listener is to monitor and respond to events in the application through the cooperation between events, event sources, event listeners and event publishers. This mechanism enables applications to handle various dynamic changes more flexibly, improving the scalability and maintainability of the system.

Events: Class Diagram

06bfa88e0436654f38bb7e6818c09f67.png

Event class name

effect

Remark

ContextRefreshedEvent

The event is published when the ApplicationContext is initialized or refreshed. It can be caused by the refresh() method in the ConfigurableApplicationtext interface.


ContextStartedEvent

The event is published when the ApplicationContext is started through the start() method of the ConfiugrableApplication() interface. You can query the database or you can restart any stopped application after receiving this event.


ContextStoppedEvent

Events are published when the ApplicationContext is stopped via the stop() method of the ConfigurableApplication interface. You can do the necessary housekeeping while receiving this event.


ContextClosedEvent

The event is published when the ApplicationContext is closed via the close() method of the ConfigurableApplicationContext interface. A closed context has reached its declared endpoint and cannot be refreshed or restarted.


RequestHandledEvent

This is a web-specific event that tells all beans that an HTTP request has been processed.

Listener for http requests and responses

Basic use

I wrote a spring event article a few years ago, you can refer to: spring events

Implementation principle

spring built-in events

05625f8d3ffb41188dcce225092c6e90.pngIn fact, it is easy to see that the principle is to use the observer mode to monitor. This is like the recent major flood event: the Xinwen Network (multicaster) announced that due to the impact of typhoons, severe flooding (events) in many provinces has recently occurred. After receiving this information (listeners), various places launched emergency and disaster relief operations.

ApplicationEventMulticaster listening mechanism

Spring also has another ApplicationEventMulticaster listening mechanism, which is used to receive events published by publishers and pass the events to registered listeners for processing.

Unlike the previously mentioned RequestHandledEvent, ApplicationEventMulticaster is a more general event broadcast mechanism for distributing various types of events throughout a Spring application.

The main functions of ApplicationEventMulticaster are as follows:

  1. Register a listener: Developers can use the addApplicationListener() method of ApplicationEventMulticaster to register a listener so that they can receive and process events of interest when the event is broadcast.

  2. Broadcast event: Once the event is published by the publisher (ApplicationEventPublisher), ApplicationEventMulticaster will receive the event and broadcast the event by calling the corresponding method of the registered listener. Listeners can match events based on type and execute custom processing logic.

  3. Asynchronous event broadcast: ApplicationEventMulticaster also supports asynchronous event broadcast, that is, event processing can be performed in a separate thread without blocking the current thread. This improves application performance and responsiveness.

ApplicationEventMulticaster is the mechanism responsible for event broadcasting in the Spring framework. It can receive events published by publishers and pass them to registered listeners for processing. It is different from RequestHandledEvent, which is a specific event class provided by Spring to be triggered after processing an HTTP request, while ApplicationEventMulticaster is a general event broadcast mechanism used to distribute various types of events throughout Spring applications.

Class Diagram:

1b13eaa030ece3de74a3d32bbc387b3a.png

a1416f6b214131f29f86f4ff5aad218e.png

Source code learning

Listener initialization

Code location: org.springframework.context.support.AbstractApplicationContext#prepareRefresh

...
//创建初始化事件监听器
if (this.earlyApplicationListeners == null) {
      this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
      // Reset local application listeners to pre-refresh state.
      this.applicationListeners.clear();
      this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    /** 初始化事件列表,自动将初始化事件监听器(自动添加不需要pubish)
     */
    this.earlyApplicationEvents = new LinkedHashSet<>();

Code location: org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory

...
//注册后置处理器用来处理ApplicationContextAware接口的回调方法
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
...
Code location: org.springframework.context.support.AbstractApplicationContext#refresh
...
// 注册事件多播器
        initApplicationEventMulticaster();

...
//事件监听器注册到多播器上
        registerListeners();

Note that the following is manually registered.

代码位置:org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster

/**事件多播器初始化 **/
protected void initApplicationEventMulticaster() {
    //获取bean工厂
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //如果没有多播器则应用多播器组件
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      //获取bean中的对象(提前初始化的)
      this.applicationEventMulticaster =
          beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isDebugEnabled()) {
        logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
    }
    //如果没有多播器
    else {
      //初始化简单的多播器
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      //注入到容器中
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isDebugEnabled()) {
        logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
            APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
            "': using default [" + this.applicationEventMulticaster + "]");
      }
    }
  }

Code location: org.springframework.context.support.AbstractApplicationContext#registerListeners

/**初始化和懒加载都会调用注册 **/
protected void registerListeners() {
    //获取所有监听器对象 
    for (ApplicationListener<?> listener : getApplicationListeners()) {
      //把监听器注册到多播器上
      getApplicationEventMulticaster().addApplicationListener(listener);
    }

    //获取自定的监听器
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    //同样把自定义的监听器注册到多播器中
    for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    //获取初始化监听器
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    //将所有初始化的监听器置为空并进行广播(清空掉)
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
      //通过多播器进行播发早期事件
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
    }
  }

Publish event listener

Code location: org.springframework.context.support.AbstractApplicationContext#finishRefresh

...
// 发布事件多播器
    publishEvent(new ContextRefreshedEvent(this));
...
protected void publishEvent(Object event, @Nullable 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<>(this, event);
      if (eventType == null) {
        eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
      }
    }

    //发布初始化(早期)事件,唯一的地方
    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);
      }
    }
  }

All listeners have been initialized here.

Use of listeners

Note that spring's default event broadcaster is: org.springframework.context.event.SimpleApplicationEventMulticaster. If not specified, it defaults to it and the default is synchronous.

Monitoring is implemented through the method multicastEvent

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
  ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
  //获取所有监听器
  for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    //获取异常支持,有则是异常事件,否则是同步发
    Executor executor = getTaskExecutor();
    if (executor != null) {
      //异步播发事件
      executor.execute(() -> invokeListener(listener, event));
    }
    else {//同步发
      invokeListener(listener, event);
    }
  }
}

at last

Many middleware are implemented through spring's support for the default listening mechanism. Of course, students who are interested in the specific implementation methods and scenarios can check out the integrated scenarios in nacos, dubbo, mq, etc., and then proceed based on the current basis if there is an opportunity in the future. study.

Reference articles:

https://www.cnblogs.com/shigongp/p/16685903.html

https://blog.csdn.net/biaolianlao0449/article/details/104246732/

https://blog.51cto.com/u_15346609/5646215

Guess you like

Origin blog.csdn.net/qq_16498553/article/details/132138138