This is the 19th day of my participation in the August Wenwen Challenge.More challenges in August

Goal:

  1. How are listeners used

  2. The principle of the listener

  3. Type of listener

  4. The concept and function of multicast

  5. How are listeners of interface types registered?

  6. Annotation type listeners and how are they registered?

  7. What if you want to do something after all the beans are loaded?


 

1. The use of listeners

Why learn listeners? Learn the listener mainly learn the design idea of the listener. For example, nacOS, which we looked at earlier, uses listeners for integration. So it’s important to understand how a listener works.

First, we need to know how to use the listener.

1.1 Principles of Spring Events

How it works: It’s observer mode

Spring’s event listening has three components:

1. ApplicationEvent: a message to be broadcast or sent. ApplicationListener: An observer in observer mode. An ApplicationListener listens for a particular event and internally defines the logic after the event occurs. Event publishing (ApplicationEventMulticaster) : corresponds to the observer pattern observed in the/themes. Responsible for notifying the observer. It provides interfaces for publishing events and adding and deleting event listeners. Maintains the relationship between events and event listeners. And is responsible for notifying event listeners when events occur.Copy the code

 

1.2 Understanding listeners

The listener is recognized above. Let’s look at an example. Let’s see by example.

Just like now there is a message, such as: inventory reduction after placing an order. Destocking is an event that requires an event player to play the event out. And then the event listener on the other end receives the message and processes it.

For example: the following demo

There is an Order Order:

package com.lxl.www.events; /** * Description * * DATE 2020/11/17. * * @author lxl. */ public class Order { private Integer id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; }}Copy the code

Next, there is an order event. The operation of orders, resulting in the increase and decrease of inventory. It’s an order event

package com.lxl.www.events; import org.springframework.context.ApplicationEvent; import java.io.Serializable; /** * Description ** order event ** event classification: DATE 2020/11/17. * * @author LXL. */ Public Class OrderEvent extends ApplicationEvent implements Serializable { private static final long serialVersionUID = 1L; private String name; public OrderEvent(Object event, String name) { super(event); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}Copy the code

Third: event listeners. Event listeners are used to listen for events. When OrderEvent publishes the destocking message, the event listener hears it.

package com.lxl.www.events; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; /** * Description * OrderEvent event listener ** * DATE 2020/11/17. ** @author LXL OrderEventListenter implements ApplicationListener<OrderEvent> {/** * when an event is published, Respond to */ @override public void onApplicationEvent(OrderEvent event) {if (event.getName().equals(" destocking ")) {system.out.println (" event listener listens for destocking "); }}}Copy the code

Is it similar to MQ?

Mq is also a subscriber, a publisher.

Let’s write a main method and run it to see what the listener looks like

package com.lxl.www.events; import org.springframework.beans.factory.parsing.SourceExtractor; import org.springframework.context.annotation.AnnotationConfigApplicationContext; / listener to use * * * * / public class MainClass {public static void main (String [] args) {AnnotationConfigApplicationContext CTX  = new AnnotationConfigApplicationContext(MainConfig.class); /** * Usage scenario: For example, there is an order placed by the user, then the corresponding inventory should be reduced. Ordering and destocking do not need to be serial. * Generally, we use an MQ to handle destocking. * * Then, listener remover is similar to MQ. */ Order Order = new Order(); order.setId(1); System. The out. Println (" order "); // Publish events. Ctx.publishevent (new OrderEvent(Order, "destock ")); System. Out.println (" log..." ); }}Copy the code

The output

The order event listener listens to the destocking log.....Copy the code

The design mode used by the listener is observer mode.

 

1.3 Types of listeners

There are two types of listeners: built-in listeners and custom listeners.

1.3.1 Built-in Listeners

Spring sets up a parent class with built-in listeners.

public abstract class ApplicationContextEvent extends ApplicationEvent { /** * Create a new ContextStartedEvent. * @param source the {@code ApplicationContext} that the event is raised for * (must not be {@code null}) */ public ApplicationContextEvent(ApplicationContext source) { super(source); } /** * Get the {@code ApplicationContext} that the event was raised for. */ public final ApplicationContext getApplicationContext() { return (ApplicationContext) getSource(); }}Copy the code

The class that implements ApplicationContextEvent is the built-in listener. Use the shortcut CTRL + H to see which classes implement ApplicationContextEvent

 

There are five types of implementations of ApplicationContextEvent.

Event instructions
ContextRefreshEvent Published when the container is instantiated or refreshed. Such as calling the refresh() method. Instantiation here means that all the beans are loaded, the post-processor is activated, all the singleton beans are instantiated, and all the container objects are ready to use. If the container support thermal overload, the refresh () can be triggered many times (XmlWebApplicationContext support hot flush, and GenericApplicationContext does not support hot refresh)
ContextStartedEvent Published when the container is started, the start() method is called and enabled means that all lifecycle will be shown to have received a signal from start
ContextStoppedEvent Published when the container stops. Lifecycle beans can be restarted by calling the stop() method, once all lifecycle beans are shown to have received the stop signal
ContextClosedEvent Published when the container is closed. That is, the close() method is called. Closing means that all singleton beans have been destroyed. Closed containers cannot be restarted or refreshed ()

 

1. ContextRefreshEvent: Published when the container is instantiated or refreshed

Let’s take a look at the source code.

Enter from the refresh() source code.

public AnnotationConfigApplicationContext(Class<? >... ComponentClasses) {// Call the constructor this(); Call this() before calling its own constructor; // register(componentClasses); // ioc container refresh interface -- very important refresh(); }Copy the code
/** * Refresh is the core method of Spring. It contains the whole process of Spring ioc, including the whole process of spring loading bean to destroy bean. Throws * @beansexception * @throws IllegalStateException */ @override public void Refresh () throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. Prepare to refresh the context prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //2. Get bean factory tell subclass is initialized, different factory implementation ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory (); . "//"/"/"/"/"/"/"/"/" }... }}Copy the code

Go to the finishRefresh() method

Protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning)  clearResourceCaches(); // Lifecycle Processor for this context. // Lifecycle processor for this context. When ApplicationContext starts or stops, it interacts with all declared beans through LifecycleProcessor(); // Propagate refresh to lifecycle processor first. Lifecycle automatically starts by calling the start() method getLifecycleProcessor().onrefresh (); // publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }Copy the code

We see that there is a release event. This event notifies the container that it has been started. Pay attention, what event is posted inside? new ContextRefreshedEvent(this). The ContextRefreshedEvent event is published.

Here’s a question: How do you extend the code after all the beans have been created?

PublishEvent (new ContextRefreshedEvent(this)) is called when all beans are created. Publish the event that the container has finished starting.

At this point we can define a listener, used to listenContextRefreshedEvent events.

/** * Create an event listener Used to monitor ContextRefreshedEvent events * / @ Component public class ContextRefreshedEventListener {/ * * * statement this is an event listener, Listening is ContextRefreshedEvent event. * @ param event * / @ EventListener (ContextRefreshedEvent. Class) public void OnApplicationEvent (ContextRefreshedEvent event) {... // After all the beans are created, write some logical code}}Copy the code

Then, put in the logic code that we need to execute after the containers are all created.

 

ContextClosedEvent: Published when the container is closed

Let’s look at the source code first, and when spring released this event.

protected void doClose() { // Check whether an actual close attempt is necessary... if (this.active.get() && this.closed.compareAndSet(false, true)) { if (logger.isDebugEnabled()) { logger.debug("Closing " + this); } LiveBeansView.unregisterApplicationContext(this); try { // Publish shutdown event. publishEvent(new ContextClosedEvent(this )); } catch (Throwable ex) { logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex); } // Stop all Lifecycle beans, to avoid delays during individual destruction. if (this.lifecycleProcessor ! = null) { try { this.lifecycleProcessor.onClose(); } catch (Throwable ex) { logger.warn("Exception thrown from LifecycleProcessor on context close", ex); } } // Destroy all cached singletons in the context's BeanFactory. destroyBeans(); // Close the state of this context itself. closeBeanFactory(); // Let subclasses do some final clean-up if they wish... onClose(); // Reset local application listeners to pre-refresh state. if (this.earlyApplicationListeners ! = null) { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Switch to inactive. this.active.set(false); }}Copy the code

Publish publishEvent(new ContextClosedEvent(this)) when doClose(); The event

Let’s take a look at what the event is. ContextClosedEvent event

If: we want to do some extension when the container is closed, we can write a listener that listens for ContextClosedEvent event when the container is closed

  

Spring built-in events, so we don’t have to define them ourselves. All we need to do is define a listener to listen for events.

 

1.3.2 Customizing Listeners

Listeners that are not spring-defined, that is, listeners that we define ourselves, are custom listeners. Let’s look at the two types of custom listeners.

Type 1: Based on interfaces

@Component public class HelloEventListener implements ApplicationListener<OrderEvent> { @Override public void OnApplicationEvent (OrderEvent Event) {if (event.getName().equals(" inventory ")) {system.out.println (" inventory....") ); }}}Copy the code

Event listeners need to implement the ApplicationListener interface, which is a generic interface whose type is the type of the event.

Second, the listener needs to bea Spring-container-managed bean, so the @Component annotation contains only one method, onApplicationEvent, which executes when the event is triggered.

Type 2: Annotation-based

@Component public class OrderEventListener { @EventListener(OrderEvent. class) public void onApplicationEvent(OrderEvent If (event.getName().equals(" unstock ")) {system.out.println (" unstock....") ); }}}Copy the code

Which event does the annotation @EventListener(OrderEvent.class) on the method listen for? OrderEvent.class

When we define listeners, we can choose to be interface-based or annotation-based.

Two. Listener source

First, listeners are declared and called in the refresh() method. Let’s take a look at the overall context of refresh(). The part marked in red is the module associated with the listener.

 

Step 5, step 9, and step 11 have all been analyzed in detail. Let’s focus on a few steps related to listeners.

2.1 Preparing the Context prepareRefresh()

While preparing the context, let’s look at what we did

 

1. The current status of the container is activated

2. Initialize property source initPropertySources(); .

In AbstractApplicationContext class does not implement this method. This is a superclass defined method. For example, we could create a custom class, override initPropertySource, and set an environment variable ABC in the change method. When the container is started, the environment variable is checked to see if it has the property, and an exception is thrown if it does not.

3. The next step is to verify the above environment variables in the presence of the specified attribute. GetEnvironment () validateRequiredProperties (); There is no will throw an exception MissingRequiredPropertiesException

4. Then the next step, event-related, creates an early event listener

// Store pre-refresh ApplicationListeners... 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); }Copy the code

So here’s the question, what was an early event listener? Early is late. How early do I mean early?

An early event is when an event listener has not yet registered with an event multicast.

Early defined events do not require manual publishEvent; early events are automatically published at the RegisterListener() stage.

What were the early event listeners? Early is late. How early do I mean early? An early event is when an event listener has not yet registered with an event multicast. Early defined events do not require manual publishEvent; early events are automatically published at the RegisterListener() stage.Copy the code

Here we define a collection, which is the following collection of event listeners. I’m just doing initialization here

 

5. Initialize a collection that holds earlier events

this.earlyApplicationEvents = new LinkedHashSet<>();

In the first step: the operation on the event is initialization. Two collections are initialized, one for early event listeners and one for early events

 

2.2 Initializing the bean factory

There are two kinds of beanFactory we use a lot today, one is XML and the other is annotation. There is a difference between XML and annotated bean factories when they are initialized.

You can see from the figure above the difference between getting bean factories in the two ways

1. AbstractRefreshableApplicationContext: based on the XML configuration files the way 2. GenericApplicationContext: annotation-based approach. Annotation based implementation of the inside of the code is very simple, just refresh the beanFactory. There is no coupled process for loading the beanDefinition. Xml-based implementation of the code, which is coupled to load the beanDefinitionCopy the code

Let’s start with annotation-based, which simply specifies the serialized ID of the bean factory

@Override protected final void refreshBeanFactory() throws IllegalStateException { if (! this.refreshed.compareAndSet(false, true)) { throw new IllegalStateException( "GenericApplicationContext does not support multiple refresh attempts: Just call the 'refresh' once "); } / / specified bean factory serialization ID enclosing the beanFactory. SetSerializationId (getId ()); }Copy the code

In addition to specifying the serialized ID of the bean factory, the XML-based beanDefinition is coupled to load

@override protected final void refreshBeanFactory() throws BeansException {// Check whether the bean factory is initialized. Destroy and close if (hasBeanFactory()) {destroyBeans(); closeBeanFactory(); } the try {/ / to create a bean plant DefaultListableBeanFactory the beanFactory = createBeanFactory (); / / set the serialization id the beanFactory. SetSerializationId (getId ()); // customizeBeanFactory(beanFactory); // Load BeanDefinition loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + GetDisplayName (), the ex); }}Copy the code

Look at the steps above.

  1. First see if there is already a factory, if there is, then destroy, shut down

  2. An empty new factory has been recreated

  3. Sets the serialization ID of the new factory

  4. Set the personalization property bean

  5. Load the bean definition. We see that using XML loads the bean definition

  6. Returns the bean factory object

This step: basically initializing the bean factory

2.3 Fill the bean factory with the prepareBeanFactory(beanFactory) property;

This step is related to listeners. Let’s take a look at the source code

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to Use the context's class loader etc. // To set the bean factory class loader to the current application beanFactory.setBeanClassLoader(getClassLoader()); / / set the standard for bean factory SPEL expression parser object (StandardBeanExpressionResolver) the beanFactory. SetBeanExpressionResolver (new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); / / for bean factory set up a resource editor PropertiesEditor attribute (for the back to bean object assignment). The beanFactory addPropertyEditorRegistrar (new ResourceEditorRegistrar(this, getEnvironment())); / / Configure the bean factory with the context callbacks. / * * * register a complete rear ApplicationContextAwareProcessor processor, Used to handle ApplicationContextAware * ApplicationContextAwareProcessor post processor is a bean. How do you use it? * * After the bean is initialized, a bunch of bean posthandlers are called. * At the initialization point, only three bean posthandlers are actually called. So when are the other post-handlers called? * is right here, Here is registered ApplicationContextAwareProcessor. * in ApplicationContextAwareProcessor# invokeAwareInterfaces method call in the other aware * So where is the invokeAwareInterfaces method called? * * is in ApplicationContextAwareProcessor# postProcessBeforeInitialization call PostProcessBeforeInitialization is invoked before the bean is initialized * * and then through the post processor addBeanPostProcessor () method, Add beans rear processor to the beanPostProcessors collection. * / the beanFactory addBeanPostProcessor (new ApplicationContextAwareProcessor (this)); /** * Ignore some of the interface's function methods, when populateBean(the second step in creating the bean: attribute assignment) * because the following interface has set methods, these methods will be automatically injected into the container without special processing. Because all methods in Aware start with set. When creating a bean and setting a property, * assigns a value to the method with the property name set+. However, these methods of Aware should be ignored. Why should they be ignored? * * For example, EnvironmentAware contains environment variables that do not require attribute assembly, So to put them to rule out * / the beanFactory ignoreDependencyInterface (EnvironmentAware. Class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found For Autowiring) as a bean. /** * Register instances of the beanFactory type ** When dependency resolution is registered, for example when parsing dependencies on beanFactory.class are registered, * When bean properties are injected, Once an attribute of type beanFactory is detected. The BeanFactory instance is registered and resolved. For example: @autoWired * ApplicationContext How can ApplicationContext be automatically assembled via @autoWired? Is assembled here. * this is also when injection attribute popularBean reflect * * / the beanFactory registerResolvableDependency (the beanFactory. Class, the beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. ApplicationListenerDetector interface way listeners. The beanFactory addBeanPostProcessor (new ApplicationListenerDetector (this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // Register default environment beans. if (! beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (! beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME,  getEnvironment().getSystemProperties()); } if (! beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); }}Copy the code

1. Set the bean factory class loader to the current application loader

2. Set the standard SPEL expression parser object for the bean factory. Who is this parser object? Is StandardBeanExpressionResolver

3. Set up a PropertiesEditor property resource editor for the bean factory, which will be used to assign values to bean objects later

4. Give the bean factory registered a rear ApplicationContextAwareProcessor processor. So here’s the post-processor class. What does this class do?

After the bean is initialized, a bunch of bean post-handlers are called

Find step 3 in doCreateBean() : Initialize the bean

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() ! = null) {the AccessController. DoPrivileged ((PrivilegedAction < Object >) () - > {/ / in the initialization is complete, Call Aware invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else {// At initialization, a lot of aware. invokeAwareMethods(beanName, bean) are called; } Object wrappedBean = bean; if (mbd == null || ! MBD. IsSynthetic ()) {/ / call before initialization beans rear processor wrappedBean = applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName); } try {// invokeInitMethods(beanName, wrappedBean, MBD); } catch (Throwable ex) { throw new BeanCreationException( (mbd ! = null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || ! MBD. IsSynthetic ()) {/ / after initialization calls beans rear processor wrappedBean = applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName); } return wrappedBean; }Copy the code

We see that a lot of Aware, invokeAwareMethods(beanName, bean) are invoked when the bean is initialized;

/** * private void invokeAwareMethods(final String beanName, Final Object bean) {/** * There are only three types of aware called in this BeanFactory. The BeanFactory has a large number of aware to call. */ if (bean instanceof BeanNameAware) {// If (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName); If (bean instanceof BeanClassLoaderAware) {ClassLoader BCL = getBeanClassLoader(); if (bcl ! = null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } // Implement BeanFactoryAware if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); }}}Copy the code

In the code above, we can see that three types of Aware are used. They are BeanNameAware, BeanClassLoaderAware and BeanFactoryAware.

What about other Aware? If we look at the comments of the beanFactory interface, we can see that a lot of Aware is called

 

At the initialization point, only three bean post-handlers are actually called. So when are the other post-handlers called?

The registered ApplicationContextAwareProcessor is here, here.

In ApplicationContextAwareProcessor# invokeAwareInterfaces method call in the other aware

Private void invokeAwareInterfaces(Object bean) {if (bean instanceof) EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); }}Copy the code

And this method, when do you execute it? Before initialization call the Bean’s rear processor execution of ApplicationContextAwareProcessor# postProcessBeforeInitialization

@Override @Nullable public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (! (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){ return bean; } AccessControlContext acc = null; if (System.getSecurityManager() ! = null) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc ! = null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { invokeAwareInterfaces(bean); } return bean; }Copy the code

We then add the bean’s post-processor to the collection of beanPostProcessors using the addBeanPostProcessor() method.

5. Ignore some interface function methods. These interfaces are primarily Aware.

beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
Copy the code

How is it that so many Aware are ignored? Why ignore it? Because all methods in Aware start with set. When creating beans and setting properties,

Assigns values to methods with the attribute name set+. In populateBean(the second step in creating the bean: attribute assignment) since the following interfaces have set*** methods, these methods will be automatically injected into the container without special processing.

For example, EnvironmentAware contains environment variables that do not require attribute assembly, so exclude them

6. Register and parse instances of the beanFactory type

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
Copy the code
When the dependency resolution is registered, such as when the resolution dependency on BeanFactory.class is registered, when the bean property is injected, the property is of type BeanFactory once detected. It registers an instance of the BeanFactory and resolves why? Such as:Copy the code
@Autowired
ApplicationContext applicationContext; .
Copy the code
Why can autoassembly be introduced via @autowired? This is the one that's assembled here and is also embodied when you inject the property popularBeanCopy the code

7.A BeanPostProcessor that registers a listener that parses an interface.

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

Let’s take a look at ApplicationListenerDetector class, its postProcessAfterInitialization method, is the third step in the createBean initialization after the implementation of the bean post processor.

@Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ApplicationListener) { // potentially not detected as a listener by getBeanNamesForType retrieval Boolean flag = this.singletonNames.get(beanName); If (Boolean.true. Equals (flag)) {// Singleton bean (top-level or inner): register on the fly /* * Register the listener of the interface type. Add it to applicationContext * The reason I'm adding it again here, To handle lazy loading situation * / this. ApplicationContext. AddApplicationListener ((ApplicationListener <? > ) bean); } else if (boil.false. Equals (flag)) {// This is the earlier event. this.applicationContext.containsBean(beanName)) { // inner bean with other scope - can't reliably process events logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " + "but is not reachable for event multicasting by its containing ApplicationContext " + "because it does not have singleton scope. Only top-level listener  beans are allowed " + "to be of non-singleton scope."); } this.singletonNames.remove(beanName); } } return bean; }Copy the code

We look at this method, and as soon as it comes in, we determine whether or not it implements the ApplicationListener interface. In other words, as we typed above, there are two ways to register listeners, one is interface mode and the other is annotation mode. What is resolved here is how the interface is implemented.

We’re going to build an impression here, because we’re going to come back to him. Why is that? This is because interface listeners are called in two places, one here and the other when the process registerListener() follows refresh(). So why call the listener twice? We’ll talk about that later