Now that we know the general concept of BeanDefinition and the lifecycle, our class can take a look at the source code! We also said that in the previous chapter BeanFactoryPostProcessors execution time is: after the scan is complete, instantiated before! Then we look at how Spring to callback BeanFactoryPostProcessors?

org.springframework.context.support.AbstractApplicationContext#refresh org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors InvokeBeanFactoryPostProcessors is scanning project into BeanDefinition and callback BeanFactoryPostProcessors place! We look at the source code is also from here to see!Copy the code

I’ll take a snippet of the code here, and copy the entire code at the end of the article:

Code one: Initialize the corresponding collection

So once I get into this method,

  1. We’ll come to the first judgment, which is whether the factory currently in use isBeanDefinitionRegistryThis judgment will return true 99% of the time. Why? Because unless you extend Spring very deeply, you inherit the top-level interface of the entire factoryAliasRegistryTo implement a completely self-implemented factory, this judgment will be skipped! At this stage, we don’t need to go into too much depth. We will confirm one thing now. The beanFactory we use must beBeanDefinitionRegistryType, this judgment must also come in;
  2. < span style = “max-width: 100%; clear: both; min-width: 1px;
  3. The second collection is the one found during executionBeanDefinitionRegistryPostProcessorWhy do you want to store him? Because he isBeanFactoryPostProcessorSubclass, we will execute first during the entire execution callBeanDefinitionRegistryPostProcessorType of post-processor in executionBeanFactoryPostProcessorType, but since it is a subclass and a parent class, to avoid repeated fetching later, let’s just do itBeanDefinitionRegistryPostProcessorStore it and waitBeanDefinitionRegistryPostProcessorAfter the method is executed, it directly executes the method of its parent class, which can also be proved from the sideBeanDefinitionRegistryPostProcessorthepostProcessBeanFactoryMethod is prior toBeanFactoryPostProcessorthepostProcessBeanFactoryMethod executes first! Of course, I will verify this with code later!

Code two, traversing the user’s own manually added post-processor

The cycle to cycle programmer to manually add the post processor (not too dig, later I will use code), if is the first call BeanDefinitionRegistryPostProcessor, if it’s spring BeanFactoryPostProcessor type, First put regularPostProcessors collection, waiting BeanDefinitionRegistryPostProcessor execution has been completed, in the spring BeanFactoryPostProcessor calls!

Code 3: began to call the BeanDefinitionRegistryPostProcessor PriorityOrdered interface

We ushered in the first paragraph of the more important code, will go to the first in the whole bean factory looking for BeanDefinitionRegistryPostProcessor type and PriorityOrdered class implements the class! Notice that at this point no one is putting a class of this type into the beanFactory. It has only one implementation, which is the BeanDefinition that Spring initialized when it broke the world, one of which meets the criteria

He is ConfigurationClassPostProcessor, this class is Spring initialization is placed in the inside of the container, when he does things very very simple, is to parse the Spring configuration class, then scanning project, will be eligible project class, Such as flow of @ Server, @ Bean class with annotations, converted to BeanDefinition, deposit and then to the container, please note that after ConfigurationClassPostProcessor performed at this time, we have value in the Spring container, With all the classes we configured that should be managed by Spring! At this point to look for will be looking for our own definition of some post-processor!

Code 4: began to call the Ordered BeanDefinitionRegistryPostProcessor interface

This code base as well as the above code, the only difference is the find is realize the Ordered the interface, because the execution ConfigurationClassPostProcessor above, container at this time within the class information and the definition of our own, So if we have a class implements the BeanDefinitionRegistryPostProcessor and implements the Ordered interface, that can be performed at this time!

Code 5: began to call the remaining BeanDefinitionRegistryPostProcessor

After the above two achieved after two kinds of BeanDefinitionRegistryPostProcessor PriorityOrdered, Ordered interface, the highest priority has been completed, Subsequent only need to carry out the remaining BeanDefinitionRegistryPostProcessor is ok, but some readers may be confused, the above two kinds of calls is just a matter of a cycle, but why need an infinite loop here?

Because, BeanDefinitionRegistryPostProcessor is an interface, in his callback methods, in some BeanDefinition method may register again, These BeanDefinition also BeanDefinitionRegistryPostProcessor types, for example, like Russian dolls, some registered every inside, who also don’t know how to set the layer, thus to be an infinite loop, as long as there is, It has been traversing to find, until the execution of so far! Something like the following:

Code 6: start calling BeanDefinitionRegistryPostProcessor superclass method

  • The first line of code means executeBeanDefinitionRegistryPostProcessorThe superclass method ofBeanFactoryPostProcessorThe return method becauseBeanDefinitionRegistryPostProcessorisBeanFactoryPostProcessorType, which is implemented to avoid repeated queries and has a higher priority than normalBeanFactoryPostProcessor!
  • The second line of code means to perform the user’s manual additionBeanFactoryPostProcessor! The back!

Code 7: Start looking for a BeanFactoryPostProcessor

The code logic is not hard to follow

  1. Find all of them firstBeanFactoryPostProcessorclass
  2. Initialize three collections, implementPriorityOrderedThe collection and implementation ofOrderedThe set of, the remainder ofBeanFactoryPostProcessorA collection of
  3. Go through everything you can findBeanFactoryPostProcessorclass
  4. To determine whenprocessedBeansThe set already exists, that is, byBeanDefinitionRegistryPostProcessorSkip the processing directly to avoid repeated execution!
  5. If it is implementedPriorityOrderedInterface, directgetBean()After being instantiated in advance, it is added to the corresponding collection. Note that it has already been instantiated!
  6. If it is implementedOrderedInterface, so put its name in the corresponding collection, notice that it is not instantiated at this point!
  7. Will be commonBeanFactoryPostProcessorPut into the corresponding collection, notice that there is no instantiation!

One thing we know from the above is that only the BeanFactoryPostProcessor of the PriorityOrdered type is instantiated and then placed into the collection!

Code 8: Start executing BeanFactoryPostProcessor

  • We implemented it firstPriorityOrderedThe collection is sorted and executed, notice that the above is already through I when it is added to the collectiongetBean()Instantiated, so you can execute directly at this point!
  • Traversal is implementedOrderedThe beanName collection is then passedgetBeanInstantiate the correspondingBeanFactoryPostProcessorAnd put it in the corresponding setorderedPostProcessors, sort after the execution!
  • So let’s go over the restBeanFactoryPostProcessorAnd thengetBeanAfter instantiation, execute directly!

Code flow chart

Complete code:

/ * * * * call BeanDefinitionRegistryPostProcessor scanning project will be a corresponding class to BeanDefinition call BeanFactoryPostProcessors callback methods * *@paramBeanFactory Bean factory *@paramRear beanFactoryPostProcessors manual provided by the processor * /
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    / / and if so, first call BeanDefinitionRegistryPostProcessors.
    Set<String> processedBeans = new HashSet<>();
    / / default is DefaultListableBeanFactory factory object So I this judgment will enter in
    if (beanFactory instanceof BeanDefinitionRegistry) {
        // It is actually the Bean factory
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // store the post-processor that the programmer supplied manually to Spring
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        / / to find in the process of executing the BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        // After looping through the bean factory handler but this debug object is indeed Null wonder why it doesn't actually enter here
        / / this is to scan the user manually add some BeanFactoryPostProcessors of her own
        // In fact, we rarely change this, except that we may manually set up a rear processor for interfacing with or developing third party components
        // This case is rarely used under normal circumstances
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            // This judgment is made to ensure that Spring's own scan handler executes first because spring has not completed the scan yet
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                // Self-defined helper processorregularPostProcessors.add(postProcessor); }}// Do not initialize FactoryBeans here: we need to keep all regular beans
        // uninitialized, let the Bean factory processor apply to it!
        / / in the implementation of BeanDefinitionRegistryPostProcessor between separate
        // PriorityOrdered, Ordered and other.
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        / / first, call PriorityOrdered BeanDefinitionRegistryPostProcessors sort (interface). This is the beanName that gets the built-in bean factory back processor
        / / in the name of the bean found out all realize BeanDefinitionRegistryPostProcessor interface
        / / call the BeanDefinitionRegistryPostProcessor subclasses PriorityOrdered at a time
        / / get BeanDefinitionRegistryPostProcessor subclasses In fact, There's only one called ConfigurationClassPostProcessor he realized PriorityOrdered interface
        / / spring BeanFactoryPostProcessor namely ConfigurationClassPostProcessor is added to the inside of the container
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
        for (String ppName : postProcessorNames) {
            // Determine if the current class implements the PriorityOrdered interface
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //getBean goes through its life cycle early
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // Add the processed object to the collection
                // Why do you want to mourn the death? Because he is belong to BeanDefinitionRegistryPostProcessor spring BeanFactoryPostProcessor itself subclasses
                // The BeanFactoryPostProcessor callback must be executed again
                / / just Spring in order to save the efficiency, avoid this part BeanDefinitionRegistryPostProcessor class is repeated to obtain, in completely call BeanDefinitionRegistryPostProcessor after class
                / / this part to interface directly to perform, that is, the spring BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor callback method is prior to realize spring BeanFactoryPostProcessor method directly
                // Since the corresponding method callback is executed before BeanFactoryPostProcessor is executed, BeanFactoryPostProcessor must be executed to filter out any previously executed BeanFactoryPostProcessor
                / / it will BeanDefinitionRegistryPostProcessor stored by the sequential execution spring BeanFactoryPostProcessor collection will skip the class inside
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        / / see the processor is added to the corresponding registered collection in aspects behind direct correction of the parent class method which BeanFactoryPostProcessors method
        registryProcessors.addAll(currentRegistryProcessors);
        / / call the Bean definition registry post-processor Here is the real one way to read class bd ConfigurationClassPostProcessor first call the beanFactory post processor
        / / here call ConfigurationClassPostProcessor post processor will register a post processor, beneath the callback
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // Clear the current handler
        currentRegistryProcessors.clear();

        / / then, call BeanDefinitionRegistryPostProcessors to realize Ordered. Ordered
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
        for (String ppName : postProcessorNames) {
            // Determine whether the current class implements the Ordered interface
            if(! processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {//getBean goes through its life cycle early
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        / / see the processor is added to the corresponding registered collection in aspects behind direct correction of the parent class method which BeanFactoryPostProcessors method
        registryProcessors.addAll(currentRegistryProcessors);
        / / call the current BeanDefinitionRegistryPostProcessor callback methods
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // Clear the current handler
        currentRegistryProcessors.clear();

        / / in the end, all other BeanDefinitionRegistryPostProcessor calls, until there is no other.
        boolean reiterate = true;
        // Why is there an endless loop here?
        / / callback because BeanDefinitionRegistryPostProcessor itself will manually register some special class, such as register a BeanDefinitionRegistryPostProcessor again
        / / class, may be manually registered class and, like dolls, so the need for constant loop iteration, so as to achieve the aim of all traversal BeanDefinitionRegistryPostProcessor
        while (reiterate) {
            reiterate = false;
            / / get all BeanDefinitionRegistryPostProcessor interface implementation class
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
            / / traverse these BeanDefinitionRegistryPostProcessor class
            for (String ppName : postProcessorNames) {
                // If it does not exist in the set, the proof will not be skipped if it has not been processed above
                if(! processedBeans.contains(ppName)) {// Add to the current set of handlers
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    // Add to the processed collection
                    processedBeans.add(ppName);
                    // Mark the scan as true for the next execution
                    reiterate = true; }}/ / sorting
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // Register the parent class into the register collection for later callback
            registryProcessors.addAll(currentRegistryProcessors);
            // Start executing these methods
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // Clears the processing set for this execution
            currentRegistryProcessors.clear();
        }

        // Now call the postProcessBeanFactory callback for all processors processed so far.
        / / BeanDefinitionRegistryPostProcessor is spring BeanFactoryPostProcessor
        // The purpose is to avoid duplicate fetching
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // Normal normal factory rear processor
        / / programmers manual provided to Spring the BeanFactory the BeanFactory. AddBeanFactoryPostProcessor (new MyBeanFactoryPostProcessor ())
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        // Invoke the factory handler registered in the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // Do not initialize FactoryBeans here: we need to keep all regular beans
    // uninitialized, let the Bean factory processor apply to it!
    // Here is the post-processor that actually gets all the BeanFactories inside the container
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);

    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        // If the preceding command has been executed, the execution will be skipped
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        / / add realized PriorityOrdered BeanFactoryPostProcessors
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        / / add implements Ordered BeanFactoryPostProcessors
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // Add the restnonOrderedPostProcessorNames.add(ppName); }}/ / first, call PriorityOrdered BeanFactoryPostProcessors.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    / / callback realized PriorityOrdered BeanFactoryPostProcessors first
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    / / then, call BeanFactoryPostProcessors to realize Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
        //getBean can be pre-instantiated into its life cycle
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    / / then, call BeanFactoryPostProcessors to realize Ordered.
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    / / in the end, all other BeanFactoryPostProcessors calls.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        //getBean can be pre-instantiated into its life cycle
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // The backend processor for the custom bean factory executed here
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear the cached merge bean definition, because the post-processor may have modified the original metadata, such as placeholders in the replacement value...
    beanFactory.clearMetadataCache();
}
Copy the code

If the understanding of the article is wrong, welcome big men private chat correction! Welcome to pay attention to the author’s public number, progress together, learn together!