This is the third day of my participation in the More text Challenge. For details, see more text Challenge

Book to text save local cache that article, in the process of our project start, there will always be some data need to be loaded, and in data loading is complete we will need some other processing (the processing must be loaded in the data can be), under normal circumstances, our daily is not going to be ok to use this thing, after all this thing more wounded body, The same is true for machines

But normal development does not mean that the project is not used, does not mean that the late will not change, after all, our goal is the stars and the sea;

Without further ado, let’s call the title first

What is the ApplicationListener

This thing is a perfect use of listener, observer mode, application event listening to the interface to be implemented. The standard Java.util. EventListener interface based on the observer design pattern. Starting with Spring 3.0, ApplicationListener can generally declare the types of events it is interested in. When the Spring ApplicationContext is registered, events are filtered accordingly and listeners are called to match only the event object (machine turn (manual dog head)).

How do you use the ApplicationListener

First we need to understand the principles

  1. Let’s take a look at the interface

    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    	void onApplicationEvent(E event);
    }
    Copy the code

Can see generics are ApplicationEvent inside, the ApplicationListener package org. Springframework. Under the context to monitor events can be used

It was the four eldest brothers;

In order to keep the article easy to understand, I decided not to translate the official notes.

* * ContextRefreshedEvent: 1. * * Event raised when an ApplicationContext gets initialized or refreshed. (when the ApplicationContext initialized or refresh Event (Ed is complete, All is complete when the time is raised))

2.**ContextClosedEvent: **Event raised when an ApplicationContext gets closed

3.**ContextStartedEvent: **Event raised when an ApplicationContext gets started.

4.**ContextStoppedEvent: **Event raised when an ApplicationContext gets stopped

There are, of course, extensions, which are not discussed here

Let’s pick up one that I’m using for my project. ContextRefreshedEvent; The others are along the same lines;

You must listen to the bean, right? You must listen to the bean, right

org.springframework.context.event.ApplicationEventMulticaster
Copy the code

I don’t want to write it. I don’t want to write it clearly

You can see the final implementation class is SimpleApplicationEventMulticaster monitoring, the official to Multicasts are the definitions of all events to all registered listeners (all event registration to the listener)

Let’s look at the abstract class AbstractApplicationEventMulticaster provides basic listener registration tool

So here we get the listener event, so we get

The first look at the loading or refresh configuration AbstractApplicationContext. The refresh () method;

Note for my English is very poor can understand, you must also line

@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. Prepare to refresh prepareRefresh(); // Tell the subclass to refresh the internal bean factory. Tell subclass refresh bean factory method, if the bean factory is destroyed to create ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory (); // Prepare the bean factory for use in this context. The context preparation uses the bean factory prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. The context subclass handles beans, loading all beans, but does not instantiate the bean postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. Call factory registered bean processors invokeBeanFactoryPostProcessors (the beanFactory); // Register bean processors that intercept bean creation. Registered bean registerBeanPostProcessors (the beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.onrefresh (); // Check for listener beans and register them.registerListeners (); // Instantiate all remaining (non-lazy-init) singletons. Initialization so that the rest of the bean - the delay finishBeanFactoryInitialization (the beanFactory); // Last step: publish corresponding event. See, this is the publish event, and it's explained here. FinishRefresh (); }}}Copy the code

* * * * initApplicationEventMulticaster () initializes the ApplicationEventMulticaster; To find whether you applicationEventMulticaster first this bean, if there is a will give event dispenser, no hand over to SimpleApplicationEventMulticaster to create; Here are the important parts of the source code

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); } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); }}Copy the code

Note that many places in this code use the singleton mode, nothing can read!!

**finishRefresh()** Let’s focus on the call to the penultimate method

protected void finishRefresh() {
		// Clear context-level resource caches (such as ASM metadata from scanning).
		clearResourceCaches();

		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}
Copy the code

PublishEvent () publishes a given event to all listeners, and there is also a piece of code here

// Multicast right now if possible - or lazily once the multicaster is initialized Or wait for the publishing released the if (this. EarlyApplicationEvents! = null) { this.earlyApplicationEvents.add(applicationEvent); } else { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); }Copy the code

EarlyApplicationEvents. This is before refresh. Early. Register local listeners before refreshing;

MulticastEvent (applicationEvent, eventType) calls invokeListener(Listener, event);

public 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); }}}Copy the code

Take a look at the getApplicationListeners(Event, Type) method; Return a Collection of ApplicationListeners matching the given event type

This method calls the ListenerCacheKey class

This search listener ends…

InvokeListener(listener, event) then calls doInvokeListener(listener, event); private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { listener.onApplicationEvent(event); }Copy the code

Look at the watch; Yo onApplicationEvent…

Wuhu… Look at the source code very tired ah…

The invocation is also simple, so (remember the Component annotation)

@Component public class MytestDemo implements ApplicationListener<ContextRefreshedEvent> { @Override public void OnApplicationEvent (ContextRefreshedEvent ContextRefreshedEvent) {system.out.println (" call to listener "); }}Copy the code