Spring IOC: registerBeanPostProcessors call chain

reference material:

Spring IoC source code learning: detailed explanation of registerbeanprostprocessors

Written at the beginning: This article is a personal study note. The content is relatively casual and mixed with personal understanding. If there are mistakes, you are welcome to correct them.

The instantiation involved in this paper refers to the construction method and the assignment of set and get methods. Initialization refers to the calling process of initialization method after instantiation, including initMethod and afterpropertieset methods.

catalogue

1, Overview

2, registerBeanPostProcessors

        1,AbstractApplicationContext#registerBeanPostProcessors

        2,registerBeanPostProcessors

2.1 preliminary preparation

2.2 instantiate the implementation class of BeanPostProcessors according to the classification

2.3. Re register internal BeanPostProcessors

3, registerBeanPostProcessors

        1,registerBeanPostProcessors

        2,addBeanPostProcessor

Summary:

1, Overview

The BeanPostProcessor interface is an extension point exposed when Spring initializes beans. The Spring IoC container allows BeanPostProcessor to add its own logical processing before and after the container initializes beans. The registerbanpostprocessors method is only registered in BeanFactory. The specific call is during bean initialization. When all beans are instantiated, the postProcessBeforeInitialization method of all beanpostprocessors will be called before the initialization method is executed, and the postProcessAfterInitialization method of all beanpostprocessors will be called after the initialization method is executed.

BeanPostProcessor has many similarities with invokebeanfactoryprocessors in terms of name and function. See here for specific differences Spring series: beanfactorypost processor and BeanPostProcessor

2, registerBeanPostProcessors

        1,AbstractApplicationContext#registerBeanPostProcessors

Simply jump to the registerbeanpopostprocessors method of the PostProcessorRegistrationDelegate class.

// AbstractApplicationContext.java
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // Register BeanPostProcessor
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

        2,registerBeanPostProcessors

In this step, we imitate and introduce the previous operation invokebeanfactoryprocessors, which is divided into three parts according to the main functions.

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    1,preparation in advance
    2,Instantiate by category BeanPostProcessors Implementation class
    3,Re register internal BeanPostProcessors
}

2.1 preliminary preparation

(1) extract all classes that implement the BeanPostProcessor interface from the previously registered cache.

(2) add beanpostprocessorchecker (mainly used to record information) to beanFactory.

After the Bean is created, the BeanPostProcessor checker will check the number of beanpostprocessors that can work on the current Bean and the total number of beanpostprocessors.

(3) establish several array stores respectively, and implement the PriorityOrdered interface, Ordered interface, BeanPostProcessor inside Spring and beanName of ordinary BeanPostProcessor.

    // 1. Find out all classes that implement the BeanPostProcessor interface
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
 

    // Target count of BeanPostProcessor
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 2. Add beanpostprocessorchecker (mainly used to record information) to beanFactory
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
 
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 3. Define different variables to distinguish: BeanPostProcessor implementing PriorityOrdered interface, BeanPostProcessor implementing Ordered interface and ordinary BeanPostProcessor
    // 3.1 priorityOrderedPostProcessors: used to store the BeanPostProcessor that implements the PriorityOrdered interface
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    // 3.2 internalPostProcessors: used to store the BeanPostProcessor inside Spring
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    // 3.3 orderedPostProcessorNames: used to store the beanName of the BeanPostProcessor that implements the Ordered interface
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // 3.4 nonOrderedPostProcessorNames: the beanName used to store ordinary BeanPostProcessor
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();

2.2 instantiate the implementation class of BeanPostProcessors according to the classification

(1) traverse the postProcessorNames in the container obtained in the previous step, and filter out the beanName that implements the PriorityOrdered interface, the Ordered interface, or none.

(2) call beanfactory for beanName that implements the PriorityOrdered interface GetBean is instantiated and stored in priorityOrderedPostProcessors. Continue to judge whether the MergedBeanDefinitionPostProcessor interface is implemented. If so, add the object to internalPostProcessors.

(3) sort the objects in priorityOrderedPostProcessors based on priorityOrderedPostProcessors, and add them to the call chain by calling the registerBeanPostProcessors method.

(4) for the Ordered interface and the ordinary BeanPostProcessor, perform steps 2 and 3 of this node in turn, instantiate and join the call chain. The difference is that the ordinary BeanPostProcessor does not sort.

    // 4. Traverse postProcessorNames to distinguish BeanPostProcessors from variables defined in 3.1 - 3.4
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 4.1 if the Bean instance corresponding to ppName implements the PriorityOrdered interface, get the Bean instance corresponding to ppName and add it to priorityOrderedPostProcessors
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                // 4.2 if the Bean instance corresponding to ppName also implements the MergedBeanDefinitionPostProcessor interface,
                // Add the Bean instance corresponding to ppName to internalPostProcessors
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 4.3 if the Bean instance corresponding to ppName does not implement the PriorityOrdered interface, but implements the Ordered interface, add ppName to orderedPostProcessorNames
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // 4.4 otherwise, add ppName to nonOrderedPostProcessorNames
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
 
    // 5. First, register the BeanPostProcessors that implement the PriorityOrdered interface
    // 5.1 sorting priorityOrderedPostProcessors
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 5.2 register priorityOrderedPostProcessors
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
 
    // 6. Next, register the BeanPostProcessors that implement the Ordered interface
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        // 6.1 get the BeanPostProcessor instance object corresponding to ppName
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        // 6.2 add the BeanPostProcessor instance object corresponding to ppName to orderdpostprocessors to prepare for registration
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            // 6.3 if the Bean instance corresponding to ppName also implements the MergedBeanDefinitionPostProcessor interface,
            // Add the Bean instance corresponding to ppName to internalPostProcessors
            internalPostProcessors.add(pp);
        }
    }
    // 6.4 sorting orderedPostProcessors
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 6.5 register orderedPostProcessors
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
 
    // 7. Register all regular BeanPostProcessors (the process is similar to 6)
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

2.3. Re register internal BeanPostProcessors

Here, the unified interface of MergedBeanDefinitionPostProcessor inherited from the previously implemented classes is removed first and then re registered to move these classes to the end of the call chain.

    // Beanposters 8. Will be moved to the end of the internal processor chain (equivalent to beanposters)
    // 8.1 sorting internal post processors
    sortPostProcessors(internalPostProcessors, beanFactory);
    // 8.2 register internalPostProcessors
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
 

    // 9. Re register ApplicationListenerDetector (similar to 8, mainly to move to the end of the processor chain)
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

3, registerBeanPostProcessors

        1,registerBeanPostProcessors

Traverse the BeanPostProcessor implementation class in the parameter and call the addBeanPostProcessor method. The beanFactory implementation class here is AbstractBeanFactory.

private static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    // Traverse postProcessors
    for (BeanPostProcessor postProcessor : postProcessors) {
        // Add the PostProcessor to the beanPostProcessors cache in BeanFactory
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

        2,addBeanPostProcessor

Add the BeanPostProcessor to the beanPostProcessors cache. The one here is removed first and then added, mainly for sorting. The hasInstantiationAwareBeanPostProcessors and hasDestructionAwareBeanPostProcessors variables are used to indicate whether beanFactory has registered InstantiationAwareBeanPostProcessors and destructionawarebeanpostprocessors. These two variables will be used in the subsequent IoC creation process

@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // If the beanPostProcessor already exists, remove it (it can have the effect of sorting. The beanPostProcessor may have been in the front. If it is removed and added, it will change to the back)
    this.beanPostProcessors.remove(beanPostProcessor);
    // Add beanPostProcessor to beanPostProcessors cache
    this.beanPostProcessors.add(beanPostProcessor);
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
        // If bean postprocessor is InstantiationAwareBeanPostProcessor, set hasInstantiationAwareBeanPostProcessors to true,
        // This variable is used to indicate whether beanFactory has registered instantiaawarebeanpostprocessors
        this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
        // If bean postprocessor is DestructionAwareBeanPostProcessor, set hasInstantiationAwareBeanPostProcessors to true,
        // This variable is used to indicate whether beanFactory has registered DestructionAwareBeanPostProcessor
        this.hasDestructionAwareBeanPostProcessors = true;
    }
}

Summary:

The registerBeanPostProcessors method is followed by invokebeanfactoryprocessors. There are many similarities between the two methods. Here is a brief summary.

        1. The invokebeanfactoryprocessors method will directly call the method of the beanfactoryprocessor implementation class, while the registerbanpostprocessors method just registers the BeanPostProcessor implementation class into the beanPostProcessors cache of BeanFactory. This is because it is not yet time for the BeanPostProcessor implementation class to be called.

        2. The implementation class of beanpostprocessor is before and after the bean instance executes the initialization method (i.e. initMethod method). The postProcessBeforeInitialization method is called before executing the initialization method, and the postProcessAfterInitialization method is called after executing the initialization method.

        3. The beanpostprocessor implementation class is the same as the BeanFactoryPostProcessor implementation class. You can also adjust your priority by implementing the PriorityOrdered and Ordered interfaces.

        4. The registerbeanpostprocessors method and invokebeanfactoryprocessors will trigger the creation of bean instances. The reason for early instantiation here is that both methods belong to the extension of beans and naturally need to be instantiated in advance.

Keywords: Spring

Added by alliance on Sun, 30 Jan 2022 18:13:07 +0200