• notice
  • Congratulations on the launch of the Sought Tech site

Spring event mechanism

concept

In a complete event system, there are the following roles

  1. Event: Describes what happened, such as request processing completed, Spring container refresh completed

  2. Event source: The generator of the event, any event must have an event source. For example, the event source of request processing is completed, and the event source of DispatcherServletSpring container refresh isApplicationContext

  3. Event broadcaster: bridge between events and event listeners, responsible for notifying events to event listeners

  4. Event listener: listen for the occurrence of events, you can do some processing in the listener

Spring events

WeChat public account: CoderLi

Our common event may be that ApplicationContextEventits subclass ContextRefreshedEventis our common event type, published after Spring has instantiated all non-lazy loaded beans.

WeChat public account: CoderLi

Let's take a look at the architecture of Spring events

WeChat public account: CodeLi

Spring listener

WeChat public account: CoderLi

event broadcaster

WeChat public account: CoderLi

WeChat public account: CoderLi

ApplicationContext support for events

WeChat public account: CoderLi

ApplicationEventPublisher This is an event publisher provided by Spring to users. The real implementation of the publishing function is still delegated to the ApplicationEventMulticaster above.

Spring provides ApplicationEventPublisherAware so that users can get this publisher for event publishing.

How to use

Spring provides two ways

  1. Implement the ApplicationListener interface

  2. Use the annotation @EventListener

Annotation implementation source code

We directly see that the EventListenerMethodProcessor class implements the interface SmartInitializingSingleton, which is called after Spring has initialized all non-lazy loaded beans.

public interface SmartInitializingSingleton {
   /**
    * Invoked right at the end of the singleton pre-instantiation phase,
    * with a guarantee that all regular singleton beans have been created
    * already. {@link ListableBeanFactory#getBeansOfType} calls within
    * this method won't trigger accidental side effects during bootstrap.
    * <p><b>NOTE:</b> This callback won't be triggered for singleton beans
    * lazily initialized on demand after {@link BeanFactory} bootstrap,
    * and not for any other bean scope either. Carefully use it for beans
    * with the intended bootstrap semantics only.
    */
   void afterSingletonsInstantiated();}

WeChat public account: CoderLi

In fact, the implementation logic is very simple

for (Method method : annotatedMethods.keySet()) {   for (EventListenerFactory factory : factories) {      if (factory.supportsMethod(method)) {
         Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
         ApplicationListener<?> applicationListener =
               factory.createApplicationListener(beanName, targetType, methodToUse);
         if (applicationListener instanceof ApplicationListenerMethodAdapter) {
            ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
         }
         context.addApplicationListener(applicationListener);
         break;
      }
   }}

Find all the annotated methods, then create a corresponding ApplicationListener respectively, and call the method by reflection after receiving the event.

public void processEvent(ApplicationEvent event) {
   Object[] args = resolveArguments(event);
   if (shouldHandle(event, args)) {
      Object result = doInvoke(args);
      if (result != null) {
         handleResult(result);
      }
      else {
         logger.trace("No result object given - no result to handle");
      }
   }}

Sequence of listener calls

We can see in AbstractApplicationEventMulticaster#retrieveApplicationListeners that it supports the order in which we specify listeners, and Spring can use many things that involve order.

  1. Implement the Ordered interface

  2. Implement the PriorityOrdered interface

  3. Using the @Ordered interface

Asynchronous call listener

By default, the event broadcaster created by Spring calls the notification listener synchronously. We can set or replace Spring's default listener to achieve the purpose of asynchronous invocation. Of course, it can also be extended to use synchronous or asynchronous according to different events. way, rather than a single either all synchronous or all asynchronous

@Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   Executor executor = getTaskExecutor();
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }}

The event propagator is initialized before spring refresh

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {      this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isTraceEnabled()) {
         logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
   }
   else {      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);      if (logger.isTraceEnabled()) {
         logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +               "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
      }
   }}

Replace the original event propagator

@Component("applicationEventMulticaster")public class TestEventMulticaster extends SimpleApplicationEventMulticaster {}


Tags

Technical otaku

Sought technology together

Related Topic

0 Comments

Leave a Reply

+