Look at the next initApplicationEventMulticaster method.

/ / multicast initialization event listeners initApplicationEventMulticaster ();Copy the code

Listeners actually use observer mode, but spring listeners are a little different from regular observer mode. We can start by looking at how a regular observer pattern is implemented. Here is a description of the Observer pattern from the book Java and Patterns:

Spring listeners are event-driven:

  • Logical execution process
  1. Event sources to publish different events
  2. When the event is published, the multicast method is called to broadcast the event, and the multicast triggers the specific listener to perform the operation
  3. Once the listener receives a specific event, it can verify that the match can handle the current event, if so, directly, and if not, do nothing
  • Actual code handling
  1. Prepare N events in advance
  2. Initialize a multicast object (create a multicast object that should contain a collection of listeners)
  3. Prepare a series of listeners
  4. Register existing listeners with the multicast
  5. Prepare event publishing to tell the multicast loop to call the listener for related logical processing

Let’s look at the actual code:

  • The event class in SpringApplicationEvent

  • Initialize the multicastSimpleApplicationEventMulticaster
Protected void initApplicationEventMulticaster () {/ / get the current bean plant, usually DefaultListableBeanFactory ConfigurableListableBeanFactory beanFactory = getBeanFactory(); / / whether the container exists bdName applicationEventMulticaster bd, multicast is a custom event listeners, Must implement ApplicationEventMulticaster interface if (the beanFactory containsLocalBean (APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {/ / if you have, The object from the bean bean factory this. ApplicationEventMulticaster = the beanFactory. GetBean (APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "] "); }} else {// If not, The default using SimpleApplicationEventMulticaster enclosing 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() + "]"); }}}Copy the code

Multicast is the collection of listeners in the superclass AbstractApplicationEventMulticaster inner class:

  • Listener objects in Spring

  • Register existing listeners with the multicast
// Check for listener beans and register them. // Check for listeners beans and register them.Copy the code
/** ** Listeners that implement ApplicationListener as listeners. * Doesn't affect other listeners, which can be added without being beans. */ protected void registerListeners() { // Register statically specified Listeners first. // Traverse the collection of listeners existing in the application and add listeners to the listeners multiplexer. > listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! // Get all bd names from the container that implement the ApplicationListener interface // put them in the ApplicationListenerBeans collection String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); // getApplicationEventMulticaster().addApplicationListener(this.getBean(listenerBeanName,ApplicationListener.class)); } // Publish early application events now that we finally have a multicaster... / / here first released early listeners collection Set < ApplicationEvent > earlyEventsToProcess = this. EarlyApplicationEvents; this.earlyApplicationEvents = null; if (! CollectionUtils.isEmpty(earlyEventsToProcess)) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}}Copy the code
  • Prepare event publishing to tell the multicast loop to call the listener for related logical processing

PublishEvent is called when the refresh is complete to publish the final event

/** * Finish refresh of this context invoking the LifecycleProcessor's * onRefresh() method and publishing the * {@link org.springframework.context.event.ContextRefreshedEvent}. */ protected void finishRefresh() { // Clear context-level Resource caches (such as ASM metadata from scanning). // Clear context-level resource caches (such as scanned ASM metadata) // Clear all resource caches in the resource loader clearResourceCaches(); // Initialize lifecycle Processor for this context. // Initialize LifecycleProcessor. If the context find 'lifecycleProcessor lifecycleProcessor Bean object, / / use the DefaultLifecycleProcessor initLifecycleProcessor (); // Propagate refresh to lifecycle processor first. For example, the auto-start component getLifecycleProcessor().onRefresh(); // Publish the final event. // Publish the final event. // Create a ContextRefreshedEvent event object and Publish it to all listeners. publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. If it is active // LiveBeansView:Sping class used to support JMX service // register the current context to LiveBeansView, To support the JMX service LiveBeansView. RegisterApplicationContext (this); }Copy the code

The multicastEvent multicast applicationEvent is called to the appropriate listener during the publishEvent method call

/ / multicast applicationEvent to appropriate listener getApplicationEventMulticaster () multicastEvent (applicationEvent, eventType);Copy the code

Finally in doInvokeListener method will be called the listener. OnApplicationEvent (event);

/** * call the listener onApplicationEvent method, Pass event * @param Listener * @param event */ @suppressWarnings ({"rawtypes", "unchecked"}) private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {// Call the listener onApplicationEvent method, The incoming event: contextrefreshListener: onapplicaitonEvent: FrameworkServlet. Enclosing onApplicationEvent () listener.onApplicationEvent(event); } catch (ClassCastException ex) {String MSG = ex.getMessage(); if (msg == null || matchesClassCastMessage(msg, event.getClass())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for // -> let's suppress the exception and just log a debug message. Log logger = LogFactory.getLog(getClass()); if (logger.isTraceEnabled()) { logger.trace("Non-matching event type for listener: " + listener, ex); }} else {// throw an exception; }}}Copy the code