Spring 5 Source Deep Parsing - - - Application Context Container refresh process

Keywords: Java Spring xml Attribute Database

In previous blogs, we have been analyzing the BeanFactory interface and its default implementation class XmlBeanFactory, but Spring also provides another interface, ApplicationContext, to extend existing functions in BeanFactory.
Both ApplicationContext and BeanFactory are used to load beans, but in contrast, ApplicationContext provides more extensions. In short, ApplicationContext contains all the functions of BeanFactory. ApplicationContext is usually preferred over Application Context, unless in some limited situations, such as when byte length has a significant impact on memory (Applet), most "typical" enterprise applications need to use Application Context.
So what functions does Application Context have more than BeanFactory? First, let's look at two different classes to load the configuration file in different ways as follows:

//Use BeanFactory Mode loading XML.
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));

//Use ApplicationContext Mode loading XML.
ApplicationContext bf = new ClassPathXmlApplicationContext("beanFactoryTest.xml");

Next, we will start with the ClassPath Xml Application Context as a starting point to analyze the overall function. First, look at its constructor:

public ClassPathXmlApplicationContext() {
}

public ClassPathXmlApplicationContext(ApplicationContext parent) {
    super(parent);
}

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}

public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
    this(configLocations, true, null);
}

public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent)
        throws BeansException {

    this(configLocations, true, parent);
}

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
    this(configLocations, refresh, null);
}

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

Setting the path is an essential step. The configuration file path can be passed in as an array in ClassPathXml Application Context, which can parse and load the array. For parsing and functional implementation, both are implemented in refresh().

Setting configuration paths

In ClassPathXml Application Context, multiple configuration files are supported to be passed in at the same time as arrays. The following is the code for setting the configuration path method:

public void setConfigLocations(@Nullable String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

If a given path contains special symbols, such as ${var}, the system variables are parsed and replaced in the method resolvePath

Extended function

After setting up the path, we can parse the configuration file and implement various functions according to the path. It can be said that refresh function contains almost all the functions provided in Application Context, and the logic in this function is very clear, so that we can easily analyze the corresponding levels and logic. Let's look at the method code below:

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //Preparing a refreshed context  
        prepareRefresh();
        //Initialization BeanFactory,And carry out XML File read  
        /* 
         * ClassPathXMLApplicationContext Contains all the features provided by BeanFactory, which will be reused in this step 
         * BeanFactory After this step, ClassPath Xml Application Context 
         * In fact, it already includes the functions provided by Bean Factory, that is, it can extract beans and other basic operations. 
         */  
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        //Yes beanFactory Perform various function filling  
        prepareBeanFactory(beanFactory);
        try {
            //Subclass Overlay Method for Additional Processing  
            /* 
             * Spring The reason why it is powerful and respected by the world is that it not only provides convenience for everyone in function, but also has its own characteristics. 
             * Perfect architecture, open architecture makes it easy for programmers who use it to expand existing functions according to business needs. This openness 
             * Design can be found everywhere in Spring, for example, in this case, an empty function is provided to implement postProcessBeanFactory. 
             * Convenient Programming Apes for Further Business Expansion 
             */ 
            postProcessBeanFactory(beanFactory);
            //Activating all kinds of beanFactory processor  
            invokeBeanFactoryPostProcessors(beanFactory);
            //Registration interception Bean Created Bean Processor, here is just registration, the real call is real getBean time 
            registerBeanPostProcessors(beanFactory);
            //Initialization for context Message Sources, i.e. message bodies in different languages, are internationalized  
            initMessageSource();
            //Initialize the application message broadcaster and put it in“ applicationEventMulticaster"bean in  
            initApplicationEventMulticaster();
            //Leave subclasses to initialize others Bean  
            onRefresh();
            //In all registered bean Search in Listener bean,Register in message broadcaster  
            registerListeners();
            //Initialize the remaining single instance (non-lazy)  
            finishBeanFactoryInitialization(beanFactory);
            //Complete the refresh process and notify the lifecycle processor lifecycleProcessor Refresh process, send out at the same time ContextRefreshEvent Notify others  
            finishRefresh();
        }
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        }
        finally {
            resetCommonCaches();
        }
    }
}

Let's briefly analyze the following steps of the code:
(1) Preparations before initialization, such as preparation and verification of system attributes or environment variables.
In some cases, the use of the project needs to read some system variables, and the setting of this variable may affect the correctness of the system, so the preparatory function provided by ClassPath Xml Application Context for us is very necessary, he can start spring ahead of the necessary environment variables. Existence verification.
(2) Initialize BeanFactory and read the XML file.
As mentioned earlier, ClassPathXml Application Context contains all the features provided for BeanFactory, so this step will reuse the configuration file read and parse functions in BeanFactory. After this step, ClassPathXml Application Context actually includes the functions provided by BeanFactory, that is, it can. Bean extraction and other basic operations have been carried out.
(3) Filling BeanFactory with various functions
@ Qualifier and @Autowire should be very familiar annotations, so these two annotations add support in this step.
(4) Subclass coverage methods do additional processing.
Spring is so powerful that it is highly praised by the world. In addition to its function, it provides traversal for everyone. On the one hand, it is a perfect architecture. Open architecture makes it easy for programmers who use it to expand their existing functions according to business needs. This open design can be seen everywhere in spring. For example, in Benefit, an empty function is provided to implement postProcessBeanFactory to facilitate programmers to further expand their business.
(5) Activate various BeanFactory processors
(6) Register the bean processor created by the intercepting bean. This is just registration. The real call is at getBean time.
(7) Initialize Message Source for Context and Internationalize Xiaoxitian in Different Languages
(8) Initialize the application message broadcaster and place it in the "application Event Multicaster" bean
(9) Leave subclasses to initialize other bean s
(10) Find listener bean s in all registered beans and register them in message broadcasters
(11) Initialize the remaining single instance (non-lazy)
(12) Complete the refresh process, notify the lifecycle processor of the refresh process, and issue ContextRefreshEvent to notify others.
Next we will explain each process in detail.

Prepare Refresh to refresh the context

/**
 * Prepare to refresh the context environment, set its start date and activity flag, and perform initialization of any property source.
 * Prepare this context for refreshing, setting its startup date and
 * active flag as well as performing any initialization of property sources.
 */
protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    // Initialize any placeholder property source in the context environment.(Empty method,Leave subclass coverage)
    initPropertySources();

    // Verify that all required property files have been put into the environment
    getEnvironment().validateRequiredProperties();

    // Allow early application events to be collected, and once you have a multicast, you can publish...
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

ObtainFreshBeanFactory - > Reads xml and initializes BeanFactory

The obtainFreshBeanFactory method literally understands that the obtainFreshBeanFactory method is an extension of beanFactory.ApplicationContext adds a lot of basic applications to it. ObtainFreshBeanFactory formally implements the beanFactory. After this function, the ApplicationFactory has all the functions of BeanFactory. Let's look at the code for this method:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //Initialization BeanFactory,And carry out XML Read the file and get the BeanFactory Recorded in the attributes of the current entity  
    refreshBeanFactory();
    //Returns the current entity's beanFactory attribute 
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

Further into the refreshBeanFactory method, the implementation of the method is in the AbstractRefreshable Application Context:

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        //Establish DefaultListableBeanFactory  
        /* 
         * When we analyzed BeanFactory in the past, we didn't know if we had any impression. The way we declared it was: BeanFactory bf.=  
         * new XmlBeanFactory("beanFactoryTest.xml"),The XmlBeanFactory inherits from DefaulltListable BeanFactory. 
         * The reader attribute of the XmlBeanDefinitionReader type is provided, which means that DefaultListableBeanFactory is the foundation of the container. Must 
         * First, instantiate. 
         */  
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        //Specify for serialization id,If necessary, let this be BeanFactory from id Deserialize to BeanFactory object  
        beanFactory.setSerializationId(getId());
        //Customized beanFactory,Setting related properties, including whether to allow objects with different definitions of the same name to be overwritten, cyclic dependencies, and settings  
        //@Autowired and Qualifier Annotation parser QualifierAnnotationAutowireCandidateResolver  
        customizeBeanFactory(beanFactory);
        //Load BeanDefiniton  
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            //Use global variable records BeanFactory Example.  
            //because DefaultListableBeanFactory Variables of type beanFactory It is a local variable within a function.  
            //So use global variables to record the parsing results  
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

Load BeanDefinition

In the first step, we mentioned the comparison between ClassPath Xml Application Context and XMLBeanFactory creation. In addition to initializing DefaultListableBeanFactory, we also need XmlBeanDefinitionReader to read XML. So the first thing to do in the loadBeanDefinitions method is to initialize XmlBeanDefinitionReader. We follow up with loadBe. In the body of an Definitions (bean Factory) method, we see that it is implemented in AbstractXml Application Context with the following code:

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}

After initializing DefaultListableBeanFactory and XmlBeanDefinitionReader, you can read the configuration file. Continue to the body of the loadBean Definitions (beanDefinitionReader) method with the following code:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        reader.loadBeanDefinitions(configLocations);
    }
}

Because the previously initialized DefaultListableBeanFactory has been registered in the XmlBeanDefinitionReader, the BeanDefinitionHolder read by the XmlBeanDefinitionReader will be registered in the DefinitionListableBeanFactory, that is, after this step, the variable bean Factory of DefaultListableBeanFactory has been registered. Includes all parsed configurations.

Function extension

prepareBeanFactory(beanFactory), as shown in the figure above, is a method of functional extension. spring has completed the configuration analysis before entering this method. Next, we will analyze the next function in detail and enter the method body.

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    //Set up beanFactory Of classLoader For the present context Of classloader  
    beanFactory.setBeanClassLoader(getClassLoader());
    //Set up beanFactory The expression language processor, Spring3 Added support for expression languages.  
    //By default, you can use#Call related attribute values in the form of {bean.xxx}  
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //by beanFactory Added one propertyEditor,This is mainly right. bean A tool for settings management such as attributes
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    //Set up several interfaces that ignore automatic assembly
    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.
    //Several special rules for automatic assembly are set up
    beanFactory.registerResolvableDependency(BeanFactory.class, 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.
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    //Increase pair AspectJ Support 
    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.
    //Add default system environment bean  
    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());
    }
}

After a detailed analysis of the code, it is found that the above functions are mainly extended in the following ways:
(1) Support for SPEL Language
(2) Increase support for attribute editors
(3) Increase support for some built-in classes, such as EnvironmentAware, MessageSourceAware injection
(4) The interface with negligible dependency function is set up.
(5) Register some fixed dependency attributes
(6) Adding AspectJ support
(7) Register relevant environmental variables and attributes in a singleton mode.

Increase support for SPEL language

Spring expression language is called "Spring Expression Language" and abbreviated as "SpEL", which is similar to OGNL language used in Struts 2x. SpEL is a separate module, relying only on core module, not on other modules, and can be used separately.
SpEL uses #{ } As delimiters, all characters in the large box number will be considered SpEL in the following format:

<util:properties id="database" location="classpath:db.properties">  
</util:properties>  
<bean id="dbcp" class="org.apache.commons.dbcp.BasicDataSource">  
  <property name="username" value="#{database.user}"></property>  
  <property name="password" value="#{database.pwd}"></property>  
  <property name="driverClassName" value="#{database.driver}"></property>  
  <property name="url" value="#{database.url}"></property>  
</bean>

The above is just the simplest way to use it. SpEL is very powerful and can greatly improve the efficiency of development. In the source code, SpEL can be parsed by registering the language parser through the code beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver()). Where will the parser be called after that?
Previously, beanFactory said that Spring has a property filling step when the bean is initialized, and in this step Spring calls the applyPropertyValues of the AbstractAutowire CapabelBeanFactory class to parse the property. At the same time, in this step, SpEL is usually parsed by the evaluateBeanDefinitionString method in AbstractBeanFactory. The method code is as follows:

protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {  
    if (this.beanExpressionResolver == null) {  
        return value;  
    }  
    Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);  
    return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));  
} 

Post-processing of BeanFactory

BeanFactory serves as the basis of container function in spring to store all loaded bean s. As an example, Spring has made a lot of extensions to BeanFactory, such as PostProcessor, which we are familiar with. Next, let's take a deep look at BeanFactory post-processing

Activate registered BeanFactoryPostProcessor

Before introducing the post-processing of BeanFactoryPostProcessor, let's briefly understand its usage. The BeanFactoryPostProcessor interface, similar to BeanPostProcessor, can handle the definition of beans (configuration metadata). That is to say, the spring IoC container allows BeanFactoryPostProcessor to instantiate beanFactoryPostProcessor in the container. What other beans read configuration metadata before and may modify it? You can also configure multiple BeanFactoryPostProcessors to control the execution order of BeanFactoryPostProcessor through the order attribute (this attribute must be credited when BeanFactoryPostProcessor implements the Ordered interface, so you should consider implementing the Ordered interface when implementing BeanFactoryPostProcessor).
If you want to change the world's bean instances (such as objects created from configuration metadata), you'd better use BeanPostProcessor. The scope of the same BeanFactoryPostProcessor is at the container level, it's only about the container you lock. If you define a BeanFactoryPostProcessor in a container, it only postprocesses beans in that container. BeanFactoryPostProcessor does not post-process beans defined in another container, even though both containers are at the same level. There are typical applications for BeanFactoryPostProcessor in spring, such as Property Placeholder Configurer.

Typical application of BeanFactoryPostProcessor: Property Placeholder Configurer

Sometimes when we read the Bean description in spring's configuration file, we encounter the following situations:

<bean id="user" class="com.yhl.myspring.demo.applicationcontext.User">
    <property name="name" value="${user.name}"/>
    <property name="birthday" value="${user.birthday"/>
</bean>

Variables appear: user.name, user.name, {user.birthday}, which is spring's decentralized configuration and can specify values for user.name, user.birthday in other configuration files, such as in the bean.properties file:

user.name = xiaoming
user.birthday = 2019-04-19

When accessing a bean named user, its name attribute is replaced by the string xiaoming. How does the spring framework know that there is such a configuration file? This is the Property Placeholder Configurer. You need to add some code in the configuration file:

<bean id="userHandler" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:bean.properties</value>
        </list>
    </property>
</bean>

The location of the configuration file is specified in this bean. In fact, there is still a problem. This userHandler is only a bean managed by the spring framework and not referenced by other beans or objects. How does spring's bean factory know that it needs configuration information from this bean? Let's look at the hierarchy of the Property Placeholder Configurer class, as follows:

From the figure above, we can see that PropertyPlaceholder Configurer indirectly inherits the BeanFactoryPostProcessor interface, which is a very special interface. When spring loads any bean configuration that implements this interface, it executes the postProcessBeanFactory method after the bean factory loads all the beans'configuration. The postProcessBeanFactory method is implemented in the PropertyResourceConfigurer class. Three methods, mergeProperties, convertProperties and processProperties, are called successively in the method. The configuration is transformed to the appropriate type. Finally, the configuration content is informed to BeanFactory.
It is by implementing the BeanFactoryPostProcessor interface that BeanFactory obtains configuration information before instantiating any bean, so that it can correctly parse variable references in the bean description file.

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    try {
        Properties mergedProps = this.mergeProperties();
        this.convertProperties(mergedProps);
        this.processProperties(beanFactory, mergedProps);
    } catch (IOException var3) {
        throw new BeanInitializationException("Could not load properties", var3);
    }
}

Custom BeanFactoryPostProcessor

Write the container post-processor of MyBeanFactoryPostProcessor, which implements the BeanFactoryPostProcessor interface, as follows:

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("Post-treatment of containers...");
    }
}

Then register the bean in the configuration file as follows:

<bean id="myPost" class="com.yhl.myspring.demo.applicationcontext.MyBeanFactoryPostProcessor"></bean>

Finally, write the test code:

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        User user = (User)context.getBean("user");
        System.out.println(user.getName());

    }
}

Activate BeanFactoryPostProcessor

After understanding the usage of BeanFactoryPostProcessor, we can deeply study the calling process of BeanFactoryPostProcessor, which is implemented in the method invokeBeanFactoryPostProcessors(beanFactory), and enter the method interior:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    // 1,First call BeanDefinitionRegistryPostProcessors
    Set<String> processedBeans = new HashSet<>();

    // beanFactory yes BeanDefinitionRegistry type
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // Definition BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        // Definition BeanDefinitionRegistryPostProcessor aggregate
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        // Circular manual registration beanFactoryPostProcessors
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            // If it is BeanDefinitionRegistryPostProcessor Examples,Call it postProcessBeanDefinitionRegistry Method,Yes bean Register
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                // If it is BeanDefinitionRegistryPostProcessor type,Call it directly postProcessBeanDefinitionRegistry
                BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            // Otherwise, treat it as normal. BeanFactoryPostProcessor Handle,Direct addition regularPostProcessors aggregate,For subsequent processing
            else {
                regularPostProcessors.add(postProcessor);
            }
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // First call implementation PriorityOrdered(Finite sort interface)Of BeanDefinitionRegistryPostProcessors
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // sort
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        // join registryProcessors aggregate
        registryProcessors.addAll(currentRegistryProcessors);
        // Call all implementations PriorityOrdered Of. BeanDefinitionRegistryPostProcessors Of postProcessBeanDefinitionRegistry Method,register bean
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // empty currentRegistryProcessors,For next use
        currentRegistryProcessors.clear();

        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        // Secondly,Call implementation Ordered(Ordinary sorting interface)Of BeanDefinitionRegistryPostProcessors
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // sort
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        // join registryProcessors aggregate
        registryProcessors.addAll(currentRegistryProcessors);
        // Call all implementations PriorityOrdered Of. BeanDefinitionRegistryPostProcessors Of postProcessBeanDefinitionRegistry Method,register bean
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // empty currentRegistryProcessors,For next use
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        // Last,Call other BeanDefinitionRegistryPostProcessors
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            // sort
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // join registryProcessors aggregate
            registryProcessors.addAll(currentRegistryProcessors);
            // Call other BeanDefinitionRegistryPostProcessors Of postProcessBeanDefinitionRegistry Method,register bean
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // empty currentRegistryProcessors,For next use
            currentRegistryProcessors.clear();
        }

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        // Call all BeanDefinitionRegistryPostProcessor(Including manual registration and registration through configuration files)
        // and BeanFactoryPostProcessor(Only manual registration)Callback function-->postProcessBeanFactory
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    // 2,If not BeanDefinitionRegistry Example,Then call its callback function directly.-->postProcessBeanFactory
    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    // 3,All of the above code has been processed. BeanDefinitionRegistryPostProcessors And manually registered BeanFactoryPostProcessor
    // Next, you need to deal with registrations through configuration files. BeanFactoryPostProcessor
    // Get all of them first BeanFactoryPostProcessor(Be careful:The collection retrieved here will contain BeanDefinitionRegistryPostProcessors)
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, Ordered, and the rest.
    // Here,It will be realized. PriorityOrdered,Ordered Processors are distinguished from other processors,Processing separately
    // PriorityOrdered Ordered Processor
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    // Ordered Ordered Processor
    List<String> orderedPostProcessorNames = new ArrayList<>();
    // Disordered Processor
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        // judge processedBeans Does it contain the current processor?(processedBeans The processors in the system have been processed.);If included,Do nothing about it.
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // Add to PriorityOrdered Ordered Processor Set
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // Add to Ordered Ordered Processor Set
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // Join the unordered processor set
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    // First call implementation PriorityOrdered Interface Processor
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    // Secondly,Call implementation Ordered Interface Processor
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    // Last,Calling the Disordered Processor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    // Cleaning up metadata
    beanFactory.clearMetadataCache();
}

Loop through the postProcessBeanFactory method in BeanFactoryPostProcessor

private static void invokeBeanFactoryPostProcessors(
        Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

    for (BeanFactoryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanFactory(beanFactory);
    }
}

Register BeanPost Processor

The BeanFactoryPostProcessor call was mentioned above, so let's explore BeanPostProcessor. But this is not a call, but a registration. The real call is actually made at the instantiation stage of the bean, which is an important step and an important reason that many functional BeanFactory do not know. Most functions in spring are extended by post-processor, which is a close-up of spring framework. But in BeanFactory, there is no automatic registration of post-processor, so it can not be used without manual registration when calling. But in Application Context, automatic registration is added, such as customizing a post-processor:

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("befor");
        return null;
    }
}

Then add the bean configuration in the configuration file:

<bean class="com.yhl.myspring.demo.applicationcontext.MyInstantiationAwareBeanPostProcessor"/>

In this way, beans loaded in BeanFactory mode will not change at the time of loading, and beans acquired in ApplicationContext mode will print out "before", which is accomplished in the registryBeanPostProcessor method.
We continue our in-depth analysis of the registryBeanPost Processors approach implementation:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    /* 
     * BeanPostProcessorChecker It's a normal print of information, and there may be some cases when spring is configured
     * The initialization of beans has been started before the processor has been registered, and then the beanPostProcessor Checker will be printed out.
     * Setting Information
     */
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    //Use PriorityOrdered To ensure order
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    //Use Ordered To ensure order
    List<String> orderedPostProcessorNames = new ArrayList<>();
    //disorder BeanPostProcessor
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    //The first step is to register all implementations PriorityOrdered Of BeanPostProcessor
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    //Registration is implemented Ordered Of BeanPostProcessor
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    //Register all disordered BeanPostProcessor
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    //Register all internals BeanFactoryProcessor
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    //Add to ApplicationListener detector
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

We can see that first we get the name array of beans of all types BeanPostProcessor.class from the container, and then we get the instance of beans through BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); finally, we get the instance of beans through registerBeanPostProcessors (beanFactory, ordered PostProcessors); The extracted BeanPostProcessor instance is added to the container's properties as follows

private static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

    for (BeanPostProcessor postProcessor : postProcessors) {
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // Remove from old position, if any
    this.beanPostProcessors.remove(beanPostProcessor);
    // Track whether it is instantiation/destruction aware
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
        this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
        this.hasDestructionAwareBeanPostProcessors = true;
    }
    // Add to end of list
    this.beanPostProcessors.add(beanPostProcessor);
}

You can see that the beanPostProcessor instance is added to the beanPostProcessors attribute of the container

Initialize Message Resources

This method is not very important. Let's leave it for later analysis.

Initial Event Broadcaster

Initialization of Application Event Multicaster is implemented in the method initApplication Event Multicaster (), which enters the method body as follows:

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 1,Default use of built-in event broadcasters,If so.
    // We can configure it in the configuration file Spring Event broadcaster or custom event broadcaster
    // for example: <bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster"></bean>
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    }
    // 2,otherwise,New event broadcaster,SimpleApplicationEventMulticaster yes spring Default Event Broadcaster
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
}

From the source code, we can see that its implementation logic is basically the same as initMessageSource. The steps are as follows:
(1) Find out if there is a bean whose name is application Event Multicaster, if it is placed in a container, and if not, initialize a system default Simple Application Event Multicaster into a container.
(2) Find the manually set application listeners and add them to the application Event Multicaster
(3) Find the bean defined as Application Listener and set it to Application Event Multicaster
(4) Initialization is completed and events in earlyApplication Events are notified (this container only stores notification information when the broadcaster is not established, and once the container is established, it will notify directly later)
(5) Notification of various bean notification events during system operation
What you can see is that application Event Multicaster is a standard observer pattern, and for its internal listener, application Listeners, each event is notified one by one.

Registered listener

protected void registerListeners() {
    // Register statically specified listeners first.
    // First,Register the specified static event listener,stay spring boot Have applications in
    for (ApplicationListener<?> 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!
    // Secondly,Register common event listeners
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // Publish early application events now that we finally have a multicaster...
    // If there were any early incidents,Event broadcasting here
    // Because in the early stage SimpleApplicationEventMulticaster Unregistered and unable to publish events,
    // So early events are stored first. earlyApplicationEvents In the collection, take them out for publication
    // So the release time node of the early event is earlier than that of other events.
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    // Early Event Broadcaster is a Set<ApplicationEvent>aggregate,Stored early events that could not be published,When SimpleApplicationEventMulticaster
    // Publish immediately after creation,Colleagues should also release their saved events
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

Let's take a look at the simple usage of Spring's Event Monitor

Define listening events

public class TestEvent extends ApplicationonEvent { 
    public String msg;
    public TestEvent (Object source ) {
        super (source );
    }
    public TestEvent (Object source , String msg ) { 
        super(source);
        this.msg = msg ; 
    }
    public void print () { 
        System.out.println(msg) ;
    }
}

Definition of monitor

public class TestListener implement ApplicationListener { 
    public void onApplicationEvent (ApplicationEvent event ) { 
        if (event instanceof TestEvent ) { 
            TestEvent testEvent = (TestEvent) event ;
            testEvent print () ;
        }
    }
}

Add configuration files

<bean id=" testListener" class=" com.test.event.TestListener " />

test

@Test
public void MyAopTest() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-aop.xml");
    TestEvent event = new TestEvent ("hello" ,"msg") ;
    context.publishEvent(event);
}

Source code analysis

protected void publishEvent(Object event, 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;
    //Supporting two kinds of events 1. Direct inheritance ApplicationEvent,2,Other times, it will be packaged as PayloadApplicationEvent,have access to getPayload Get the real notification content
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent) event;
    }
    else {
        applicationEvent = new PayloadApplicationEvent<Object>(this, event);
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
        }
    }

    // Multicast right now if possible - or lazily once the multicaster is initialized
    if (this.earlyApplicationEvents != null) {
        //If a prefabricated line is added to the prefabricated line, the prefabricated line is set to null,All of them will be implemented directly in the future.
        this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
        //Radio broadcast event Event
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }

    // Publish event via parent context as well...
    //father bean Same broadcast
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        }
        else {
            this.parent.publishEvent(event);
        }
    }
}

Find all the listeners and traverse them in turn. If there are thread pools, send them by thread pools. If not, send them directly. For larger concurrency, we should adopt thread pool mode to separate sending notifications from real business logic.

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

Call invokeListener

protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
        try {
            listener.onApplicationEvent(event);
        }
        catch (Throwable err) {
            errorHandler.handleError(err);
        }
    }
    else {
        try {
            listener.onApplicationEvent(event);
        }
        catch (ClassCastException ex) {
            // Possibly a lambda-defined listener which we could not resolve the generic event type for
            LogFactory.getLog(getClass()).debug("Non-matching event type for listener: " + listener, ex);
        }
    }
}

Initialize other singleton beans (non-lazy loading)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    // Judge whether or not ConversionService(bean Attribute Type Conversion Service Interface),And initialization
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
            && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }

    //
    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    // If beanFactory Not included in EmbeddedValueResolver,Add one to it EmbeddedValueResolver
    // EmbeddedValueResolver-->analysis bean Occupants and expressions in
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    // Initialization LoadTimeWeaverAware Type bean
    // LoadTimeWeaverAware-->Load Spring Bean Timely weaving into third-party modules,as AspectJ
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }

    // Stop using the temporary ClassLoader for type matching.
    // Release Temporary Class Loader
    beanFactory.setTempClassLoader(null);

    // Allow for caching all bean definition metadata, not expecting further changes.
    // Frozen cached BeanDefinition metadata
    beanFactory.freezeConfiguration();

    // Instantiate all remaining (non-lazy-init) singletons.
    // Initialize other non-delayed loading cases bean
    beanFactory.preInstantiateSingletons();
}

We focus on beanFactory. preInstantiate Singletons ();

@Override
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    final FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                        ((SmartFactoryBean<?>) factory)::isEagerInit,
                                getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                getBean(beanName);
            }
        }
    }

}

Complete the refresh process, notify the lifecycle processor of the refresh process, and issue a ContextRefreshEvent notification

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

    // Initialize lifecycle processor for this context.
    // Initialization Life Cycle Processor
    initLifecycleProcessor();

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

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

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

Posted by sweetmaster on Fri, 27 Sep 2019 01:43:47 -0700