The body of the

In the previous article, the general process of beanFactory post-processing was analyzed, and a general summary was made. Now on to the next flow.

1. InvokeBeanFactoryPostProcessors method

        / / classes and methods: org. Springframework. Context. Support. AbstractApplicationContext# invokeBeanFactoryPostProcessors
        // Invoke factory processors registered as beans in the context.
        invokeBeanFactoryPostProcessors(beanFactory);
Copy the code

The annotation translates as: invoke the factory handler registered as a bean in the context.

    / / classes and methods: org. Springframework. Context. Support. AbstractApplicationContext# invokeBeanFactoryPostProcessors
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
      PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
      // omit some code,,,
   }
Copy the code

2. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors

. The above code calls the PostProcessorRegistrationDelegate invokeBeanFactoryPostProcessors () method, the following into the method, the code is more, the method is also long, it is better to breakpoint debugging to this method, Step by step.

    / / classes and methods: org. Springframework. Context. Support. PostProcessorRegistrationDelegate# invokeBeanFactoryPostProcessors
    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

      // Invoke BeanDefinitionRegistryPostProcessors first, if any. 
      / / first call BeanDefinitionRegistryPostProcessors type
      Set<String> processedBeans = new HashSet<>();//processedBeans is used to save beanName that has been called.
        / / the beanFactory is used when creating DefaultListableBeanFactory, and realized DefaultListableBeanFactory BeanDefinitionRegistry interface, so meet the condition here
      if (beanFactory instanceof BeanDefinitionRegistry) {
         BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
         // Define the BeanFactoryPostProcessor collection
         List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
         / / define BeanDefinitionRegistryPostProcessor collection
         List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            / / traverse beanFactoryPostProcessors, carries on the classification and then into the corresponding collection
            / / at the breaking point, to enter, if use AnnotationConfigApplicationContext beanFactoryPostProcessors is null
            / / enter, if use springboot startup mode beanFactoryPostProcessors there is value, specific here did not elaborate, interested can interrupt point in research
         for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
               BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;
               registryProcessor.postProcessBeanDefinitionRegistry(registry);
               registryProcessors.add(registryProcessor);
            }
            else{ regularPostProcessors.add(postProcessor); }}/ / create BeanDefinitionRegistryPostProcessor collection
         List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

         // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
         / / as a first step, call the BeanDefinitionRegistryPostProcessors PriorityOrdered interface
         String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
         for (String ppName : postProcessorNames) { // filter through
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// Filter those implementing the PriorityOrdered interface
               currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
               processedBeans.add(ppName);
            }
         }
         sortPostProcessors(currentRegistryProcessors, beanFactory);/ / sorting
         registryProcessors.addAll(currentRegistryProcessors); // categorize
         / / call in to place breakpoints, there will be a ConfigurationClassPostProcessor currentRegistryProcessors
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 
         currentRegistryProcessors.clear();/ / clean up

         // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
         / / then calls the implement BeanDefinitionRegistryPostProcessors Ordered
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
         for (String ppName : postProcessorNames) {
            // Traversal filters that implement Ordered interface and are not called.
            if(! processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory);/ / sorting
         registryProcessors.addAll(currentRegistryProcessors);/ / classified
        / / call, breakpoint debugging found this place currentRegistryProcessors is null
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
         currentRegistryProcessors.clear();/ / clean up

         // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
         / / in the end, call other BeanDefinitionRegistryPostProcessors, until no
         boolean reiterate = true;
         while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
            for (String ppName : postProcessorNames) {
               if(! processedBeans.contains(ppName)) {// Check if it has already been called
                  currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                  processedBeans.add(ppName);
                  reiterate = true;
               }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);/ / sorting
            registryProcessors.addAll(currentRegistryProcessors);/ / add
            // call breakpoint debug, find this place is also null
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();/ / clean up
         }
         // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
         / / call BeanFactoryPostProcessors callback methods
         invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);/ / BeanDefinitionRegistryPostProcessor callback
         invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);// The BeanFactoryPostProcessor callback
      }
      else {
         // Invoke factory processors registered with the context instance.
         invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
      }
       // Call BeanFactoryPostProcessor
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the bean factory post-processors apply to them!
      String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);
      // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
      // Ordered, and the rest.
      // Classify and sort registered beanFactory PostProcessors
      List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
      List<String> orderedPostProcessorNames = new ArrayList<>();
      List<String> nonOrderedPostProcessorNames = new ArrayList<>();
      for (String ppName : postProcessorNames) {
         if (processedBeans.contains(ppName)) { // Exclude those already called
            // skip - already processed in first phase above
         }
         else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// implement PriorityOrdered
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
         }
         else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { // Implement Ordered
            orderedPostProcessorNames.add(ppName);
         }
         else {/ / the othernonOrderedPostProcessorNames.add(ppName); }}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
       / / call PriorityOrdered BeanFactoryPostProcessors
      sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
      invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

      // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        / / call BeanFactoryPostProcessors to realize Ordered
      List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
      for (String postProcessorName : orderedPostProcessorNames) {
         orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
      }
      sortPostProcessors(orderedPostProcessors, beanFactory);/ / sorting
      invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);/ / call

      // Finally, invoke all other BeanFactoryPostProcessors.
       / / in the end, call the remaining BeanFactoryPostProcessors
      List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
      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...
      beanFactory.clearMetadataCache();// Clear the cache
   }
   
Copy the code

This method is more code, need to be patient to see. First go to see its notes, the general process of this method, is what to understand clearly. In fact, these code about a process is relatively simple. And the source of the existing notes also explain the process is very clear, I also wrote some notes above.

This method is mainly perform BeanFactoryPostProcessors interface implementation class. Note that: The implementation class, either from parameter beanFactoryPostProcessors to come in, or have been registered in the beanFactory ok, however, at this time, the beanFactory just initialization, hasn’t been scanned the project, That is to say, didn’t start automatically scan, if you want to implement custom BeanFactoryPostProcessors interface, so the spring should be effective method to make a custom interface, or manually register information to the beanFactory custom interface.

There is, as a result of inherited BeanFactoryPostProcessors BeanDefinitionRegistryPostProcessor interface interface, So realize BeanDefinitionRegistryPostProcessor interface classes will be picked up and calls (specific invokeBeanDefinitionRegistryPostProcessors method in the code, This method is to call cycle postProcessBeanDefinitionRegistry method), then the call to the rest of the implementation class (specific invokeBeanFactoryPostProcessors method in the code, That method loops through the postProcessBeanFactory method, and it is possible that those implementation classes also implement PriorityOrdered and Ordered interfaces to filter and sort. Here’s his flow chart:

3. The piecewise

Let’s look at the code fragment above:

SpringBoot version 2.5.2, spring-Context version 5.2.8.release

3.1 the ginseng processing (beanFactoryPostProcessors)

The BeanFactoryPostProcessor parameter passed in is classified and then called. Is actually choose BeanDefinitionRegistryPostProcessor implementation, then call postProcessBeanDefinitionRegistry method

    for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryProcessor =
                    (BeanDefinitionRegistryPostProcessor) postProcessor;
            registryProcessor.postProcessBeanDefinitionRegistry(registry);
            registryProcessors.add(registryProcessor);
        }
        else{ regularPostProcessors.add(postProcessor); }}Copy the code

  • ConfigurationWarningsPostProcessor
  • CachingMetadataReaderFactoryPostProcessor

3.2 BeanDefinitionRegistryPostProcessor – PriorityOrdered

Is chosen from among the beanFactory BeanDefinitionRegistryPostProcessor type of bean, and implements the PriorityOrdered interface.

        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);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();
Copy the code

In this code debugging, will find that there is only one class, is ConfigurationClassPostProcessor class.

3.3 BeanDefinitionRegistryPostProcessor – Ordered

Is chosen from among the beanFactory BeanDefinitionRegistryPostProcessor type of bean, and implements the Ordered interface.

    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); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()); currentRegistryProcessors.clear();Copy the code

Breakpoint debugging, this place don’t have class, namely currentRegistryProcessors is null.

3.4 BeanDefinitionRegistryPostProcessor – other and callback

  1. Execute the restBeanDefinitionRegistryPostProcessorThe type ofbean, and finally invokes the callback methodinvokeBeanFactoryPostProcessors.
    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;
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();
    }

    // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
    invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
Copy the code

3.5 spring BeanFactoryPostProcessor classified

Get the BeanFactoryPostProcessor in beanFactory, skip it, and sort it by PriorityOrdered, Ordered.

        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 (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
         }
         else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
         }
         else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
         }
         else{ nonOrderedPostProcessorNames.add(ppName); }}Copy the code

3.6 BeanFactoryPostProcessor invocation and cache cleaning

Call the BeanFactoryPostProcessor, which was sorted in step 5, and finally clear the cache

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

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

      // Finally, invoke all other BeanFactoryPostProcessors.
      List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
      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...
      beanFactory.clearMetadataCache();

Copy the code

The last

Know from the above code, the two important interfaces, one is spring BeanFactoryPostProcessor, another is BeanDefinitionRegistryPostProcessor interface. Including BeanDefinitionRegistryPostProcessor interface inherits the spring BeanFactoryPostProcessor interface, but the function of the two interfaces is different, specific need to see how their respective implementation class.

In the process of debugging, the emergence of a ConfigurationClassPostProcessor class, this class is actually one of the most important during the implementation of the overall approach. The name gives you an idea of what this class does: handles configuration classes. About ConfigurationClassPostProcessor here did not elaborate.