preface

  • Blog last spring 5.0 x source learning four series: AnnotationConfigApplicationContext class register method of register is mainly introduced the role. Now we’ll get to the most important step in initializing the Spring environment: the refresh method

Refresh source code black box theory

  • In this chapter, we first put the source code of each method of execution flow first listed, and then according to each specific method for analysis
  • The source code
    
            @Override
        public void refresh(a) throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
    
                // Get the Spring bean factory
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                // When this method is complete, spring's bean singleton container contains three beans,
                // Are systemEnvironment, environment, systemProperties respectively
                / / will add ApplicationContextAwareProcessor post processor at the same time, the processor has not gone
                // Spring's bean initializers are directly new internally, and the handler is used to process the implementation
                // The ApplicationContextAware interface bean calls the overridden set method, so it can be used
                // This method gets the spring context object
                prepareBeanFactory(beanFactory);
    
                try {
                    // This method does nothing and has no internal logic
                    postProcessBeanFactory(beanFactory);
    
                    // Call the post-processor. This method is so important that it will be parsed in a subsequent source code interpretation series
                    // What does it do
                    // 1. Process the manually added BeanFactoryPostProcessor
                    / / 1.1 call manually add BeanDefinitionRegistryPostProcessor and added to store it in the collection,
                    // The collection name is: registryProcessors
                    / / 1.2 store manually add spring BeanFactoryPostProcessor,
                    // The collection name is regularPostProcessors
                    // Note: the above step is if else logic, save one other will not save
                    / / 2. Perform BeanDefinitionRegistryPostProcessor type and the implementation PriorityOrdered answered
                    // Port rear processor. The default execution spring built-in BeanDefinitionRegistryPostProcessor
                    / / post processor (ConfigurationClassPostProcessor), after the post processor was implemented,
                    // All beans that can be scanned are registered with the bean factory as BeanDefinition
                    / / 3. Perform BeanDefinitionRegistryPostProcessor type and implementation
                    // Ordered The post-processor of the interface
                    / / 4. Implement to add @ Component way BeanDefinitionRegistryPostProcessor type didn't realize
                    // Ordered and PriorityOrdered interface rear handlers
                    Implement regularPostProcessors and registryProcessors data structures
                    // BeanFactoryPostProcessor type of back processor (execute here
                    / / ConfigurationClassPostProcessor postProcessBeanFactory method, mainly
                    // Generate the Class object of the Cglib proxy Class for the fully configured Class and modify its beanDefinition information to the generation
                    // Class information
                    // 6. Execute a BeanFactoryPost added as @Component that implements the PriorityOrdered interface
                    // Processor Specifies the rear Processor
                    // 7. Execute the BeanFactoryPost that adds and implements the Ordered interface in @Component form
                    // Processor Specifies the rear Processor
                    // 8. Execute to add beans that do not implement the PriorityOrdered and Ordered interfaces as @Component
                    // FactoryPostProcessor is the rear processor
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register the BeanPostProcessor in the Spring Bean factory
                    / / including spring built-in, scan (eg: use ImportBeanDefinitionRegistrar, AOP implementations),
                    / / yourself manually add (manually add BeanDefinitionRegistryPostProcessor,
                    // Register a BeanPostProcessor bean in it.
                    //
                    // By default, spring has three built-in BeanPostProcessors:
                    / / org. Springframework. Context. The annotation. InternalAutowiredAnnotationProcessor = > the @autowired annotation processing
                    / / org. Springframework. Context. The annotation. @ internalRequiredAnnotationProcessor = > processing Required annotations
                    / / org. Springframework. Context. The annotation. InternalCommonAnnotationProcessor = > rear of dealing with the Common annotations processor
                    // As well as various BeanPostProcessor processes that implement the PriorityOrdered and Ordered interfaces
                    // The main thing is to create these beans through the Spring Bean factory, add them to a list of beanPostProcessors, and broadcast them
                    // mechanism call
                    // I think there are two reasons to use a list instead of a set
                    // 1. The list is Ordered, and some BeanPostprocessors implement PriorityOrdered and Ordered interfaces, so they should be executed in a certain order
                    // list traversal is faster than list traversal
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.
                    / / the internationalization
                    initMessageSource();
    
                    // Initialize event multicaster for this context.
                    // Initializes spring's event-driven model implementer
                    initApplicationEventMulticaster();
    
                    // This method does nothing and has no internal logic
                    onRefresh();
    
                    // Register your manually added listeners and spring scanned listeners
                    / / manually add listeners: call the spring context addApplicationListener method, eg: AnnotationConfigApplicationContext context method
                    // Listeners scanned by Spring: listeners identified by the @Component annotation
                    // What if I add a listener with the @Component annotation and manually call addApplicationListener?
                    // It doesn't matter, execute it twice, because Spring handles manually added listeners differently from scanned listeners. Manually added listeners are Java objects, but spring scans them
                    // The listener is a bean, so the two listeners are different objects of the same type
                    Note, however, that the listener added manually is a Java Object, whereas Spring scans out a bean
                    registerListeners();
    
                    // Start creating non-abstract, non-prototype, non-lazy-loaded beans and process bean autowage
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Complete the refresh and publish the corresponding event
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Exception encountered during context initialization - " +
                                "cancelling refresh attempt: " + ex);
                    }
    
                    // Destroy already created singletons to avoid dangling resources.
                    destroyBeans();
    
                    // Reset 'active' flag.
                    cancelRefresh(ex);
    
                    // Propagate exception to caller.
                    throw ex;
                }
    
                finally {
                    // Reset common introspection caches in Spring's core, since we
                    // might not ever need metadata for singleton beans anymore...resetCommonCaches(); }}}Copy the code
  • conclusion
    1. From the comments in the source code:refreshThe method is basically doing thisPopulate spring’s entire bean environment (previous Spring environments were empty shells), including scanning beans, initializing non-abstract, singleton, non-lazy-loaded beans, and initializing the Spring event-driven model.
    2. A diagram of the Spring context is provided to give you an idea of the structure

Second, the leading role of this blog: invokeBeanFactoryPostProcessor method

  • The flow chart
  • The source code comments
    	public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List
             
               beanFactoryPostProcessors)
              {
       
           // Invoke BeanDefinitionRegistryPostProcessors first, if any.
           Set<String> processedBeans = new HashSet<>();
    
           / / incoming DefaultListableBeanFactory bean factory is also a BeanDefinitionRegistry, it implements this interface
           if (beanFactory instanceof BeanDefinitionRegistry) {
               BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    
               // The factoryPostProcessor that is manually added to BeanFactoryPostProcessor,
               // eg: context.addBeanFactoryPostProcessor(new MyBeanDefinitionRegistryPostProcessor());
               / / which context is AnnotationConfigApplicationContext object, but it's just execution to the parent class AbstractApplicationContext method
               List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    
               / / used to store manually add BeanDefinitionRegistryPostProcessor processor, is also a way of executing the above comment said
               / / because spring BeanFactoryPostProcessor have a subclass called BeanDefinitionRegistryPostProcessor
               RegularPostProcessors and registryProcessors are just lists to store manually added BeanFactoryPostProcessors
               List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    
               for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                   if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                       BeanDefinitionRegistryPostProcessor registryProcessor =
                               (BeanDefinitionRegistryPostProcessor) postProcessor;
                       / / to manually add BeanDefinitionRegistryPostProcessor would be here for the first time is called, so here is the first time post processor is called
                       registryProcessor.postProcessBeanDefinitionRegistry(registry);
                       / / store manually add BeanDefinitionRegistryPostProcessor, subsequent use
                       registryProcessors.add(registryProcessor);
                   }
                   else {
                       / / store manually add spring BeanFactoryPostProcessor, subsequent useregularPostProcessors.add(postProcessor); }}// This list is used to store spring's built-in BeanFactoryPostProcessor
               List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    
               / / here is called realized PriorityOrdered interface BeanDefinitionRegistryPostProcessor post processor
               / / just to get here, call is below invokeBeanDefinitionRegistryPostProcessors (currentRegistryProcessors, registry); To complete the
               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);
               / / here first call the class is spring built-in beanName called org. Springframework. Context. The annotation. InternalConfigurationAnnotationProcessor,
               / / class named ConfigurationClassPostProcessor bean
               / / because in spring built-in six bean only it is to implement the BeanDefinitionRegistryPostProcessor interface
               / / so ConfigurationClassPostProcessor class is the main purpose of this time is called:
               // 1. Generate a factoryId for the bean factory and record it
               // 2. Loop through the configuration classes passed in (i.e., the corresponding classes in the register method)
               // 2.1 determine whether BeanDefinition is AnnotatedBeanDefinition type according to class's BeanDefinition (because Java config mode is currently considered, only this type is considered)
               Check whether the incoming class has @Configuration annotations or (@Component and @ComponentScan and @import and ImportResource annotations) or whether there are internal methods that add @bean annotations and parse them
               invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
               currentRegistryProcessors.clear();
    
               // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
               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); currentRegistryProcessors.clear();// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
               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);
                   currentRegistryProcessors.clear();
               }
    
               // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
               / / this is the first call to manually added to the spring BeanDefinitionRegistryPostProcessor rewrite BeanFactoryPostProcessors interface (postProcessBeanFactory) method
               / / because BeanDefinitionRegistryPostProcessor is spring BeanFactoryPostProcessor class inheritance. So I rewrote the BeanFactoryPostProcessor method as well
               / / when the first call to just call the method in the BeanDefinitionRegisterPostProcessor
               invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
               // This is the first call to the BeanFactoryPostProcessor that was manually added to Spring
               invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
           }
    
           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!
           // Call the non-manually added BeanFactoryPostProcessor postprocessor with the @Component annotation
           / / as in the previous step calls ConfigurationClassPostProcessor this type (BeanDefinitionRegistryBeanFactory) post processor, scanned the package has been successful,
           / / and will scan the information encapsulated into ScannedGenericBeanDefinition BeanDefinition, so according to the type to find the beans including registered in the form of annotation
           / / spring BeanFactoryPostProcessor, but also include ConfigurationClassPostProcessor because it implements BeanDefinitionRegistryBeanFactory interface also
           // Inherits the BeanFactoryPostProcessor interface
           String[] postProcessorNames =
                   beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);
    
           // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
           // Ordered, and the rest.
           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); }}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
           // Parse BeanFactoryPostProcessor that implements the PriorityOrdered interface and execute it in sequence
           sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
           invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
           // Parse the BeanFactoryPostProcessor that implements the Ordered interface and execute it in order
           List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
           for (String postProcessorName : orderedPostProcessorNames) {
               orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
           }
           sortPostProcessors(orderedPostProcessors, beanFactory);
           invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    
           // Calls a post-processor that implements BeanFactoryPostProcessor that does not implement the PriorityOrdered and Ordered interfaces
           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...
           beanFactory.clearMetadataCache();
       }
    Copy the code

Iii. Project test demo

3.1 Project Structure

3.1.1 Structural panorama

3.1.2 Various details and functions

  1. Project entry (Entry to start the Spring environment)
  2. Fully configured class that defines the package to scan
  3. Manually add BeanDefinitionRegistryPostProcessor
  4. Manually added BeanFactoryPostProcessor
  5. By the spring scan BeanDefinitionRegistryPostProcessor but not Ordered and PriorityOrdered interface
  6. By spring scan out BeanDefinitionRegistryPostProcessor Ordered interface is achieved, and the weight of 1 = > low weight, priority is carried out
  7. By spring scan out BeanDefinitionRegistryPostProcessor Ordered interface is achieved, and the weight for the 2 = > weight low, priority is carried out
  8. By spring scan out BeanDefinitionRegistryPostProcessor PriorityOrdered interface is achieved, and the weight of 1 = > low weight, priority is carried out
  9. By spring scan out BeanDefinitionRegistryPostProcessor PriorityOrdered interface is achieved, and the weight for the 2 = > weight low, priority is carried out
  10. BeanFactoryPostProcessor scanned by Spring
  11. The BeanFactoryPostProcessor scanned by Spring implements the Ordered interface, and the lower the weight is, the higher the priority is
  12. The BeanFactoryPostProcessor scanned by Spring implements the Ordered interface, and the lower the weight is, the higher the priority is
  13. BeanFactoryPostProcessor scanned by Spring implements a PriorityOrdered interface. The lower the weight is, the higher the priority is
  14. BeanFactoryPostProcessor scanned by Spring implements a PriorityOrdered interface. The lower the weight is, the higher the priority is

3.2 Execution process and principle

3.2.1 handle manually add spring BeanFactoryPostProcessor (including BeanDefinitionRegistryPostProcessor and spring BeanFactoryPostProcessor)

3.2.2 execution BeanDefinitionRegistryPostProcessor type and implements the rear PriorityOrdered interface of the processor

This step is so important that a follow-up blog post will be devoted to this step, describing exactly what it does

3.2.3 execution BeanDefinitionRegistryPostProcessor type and implements the Ordered the rear of the interface processor, implementation process and the second step is the same

3.2.4 BeanDefinitionRegistryPostProcessor type and unrealized Ordered interface and rear PriorityOrdered interface processor, the execution and the third step the same

3.2.5 BeanDefinitionRegistryPostProcessor types of spring BeanFactoryPostProcessor processing

  • The above four steps are called BeanDefinitionRegistryPostProcessor type of post processor, will begin to call back rear spring BeanFactoryPostProcessor types of processors. Because there are manually add BeanDefinitionRegistryPostProcessor is rear spring BeanFactoryPostProcessor type of processor (inheritance), So this step will begin to call manually add BeanDefinitionRegistryPostProcessor post processor of spring BeanFactoryPostProcessor method and manually add spring BeanFactoryPostProcessor

     // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
     / / this is the first call to manually added to the spring BeanDefinitionRegistryPostProcessor rewrite BeanFactoryPostProcessors interface (postProcessBeanFactory) method
     / / because BeanDefinitionRegistryPostProcessor is spring BeanFactoryPostProcessor class inheritance. So I rewrote the BeanFactoryPostProcessor method as well
     / / when the first call to just call the method in the BeanDefinitionRegisterPostProcessor
     invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
     // This is the first call to the BeanFactoryPostProcessor that was manually added to Spring
     invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    Copy the code

3.2.6 Execute the BeanFactoryPostProcessor postprocessor that has been added and implemented as an @Component to the PriorityOrdered interface

3.2.7 Implement the BeanFactoryPostProcessor that adds and implements the Ordered interface in @Component form

3.3 about “3.2.3 execution BeanDefinitionRegistryPostProcessor type and implements the Ordered the rear of the interface processor, implementation process and the second step is the same,” the two questions

  • The original image
The problem The answer
Q1: Why is a post-processor implementing the PriorityOrdered interface also implemented here? Hasn’t that been done already? Because the PriorityOrdered interface inherits the Ordered interface, the postulated processor that implements the PriorityOrdered interface is also removed when dealing with interfaces that implement the Ordered type. And indeed have been executed before the rear realized PriorityOrdered interface processor (ConfigurationClassPostProcessor), but this is a special post processor, because it, We can then get the post-processor added as the @Component annotation. In which, when executed, is the most important of the bean factory only an implementation of a rear PriorityOrdered interface BeanDefinitionRegistryPostProcessor type of processor, That’s why Spring uses the set of processedBeans to store the post-processor that has been executed
Q2: why are only postprocessors of the 2,3,4,5 subscripts of postProcessorNames executed? Because they both implement the Ordered interface, although some postprocessors implement the PriorityOrdered interface, the PriorityOrdered interface inherited from Ordered

Third, summary

  • InvokeBeanFactoryPostProcessor method is to call the main function of post processor, here need most is mainly to a rear processor is ConfigurationClassPostProcessor, It not only did the scan work also do the configuration for the whole class to generate additional proxy objects work (because it has two identities: one is the BeandefinitionRegistryPostProcessor another spring BeanFactoryPostProcessor)

  • About BeanDefinitionRegistryPostProcessor and rear spring BeanFactoryPostProcessor processor and the difference between a role

    type Provides the API role
    BeanDefinitionRegistryPostProcessor BeanDefinitionRegistry BeanDefinition is a beanDefinition registry, which is typically used to register a beanDefinition
    BeanFactoryPostProcessor ConfigurableListableBeanFactory It’s essentially Spring’s bean factory, but receives it with a parent class. The bean factory is now available, and we can do indescribable things to the bean, such as changing the bean’s class to create proxy objects for it,
  • Using BeanDefinitionRegistryPostProcessor and rear spring BeanFactoryPostProcessor processor’s attention

    • Understand each post processor execution order eg: manually add BeanDefinitionRegistryPostProcessor type of post processor, than spring built-in and to the rear of the @ Component way to add processors are carried out first
    • Familiar with the different of the rear of the interface processor execution order, eg: BeanDefinitionRegistryPostProcessor and rear spring BeanFactoryPostProcessor type of processor are priority implementation PriorityOrdered interface
  • Spring source code to learn the corresponding GitHub address github.com/AvengerEug/…

  • I am a slow walker, but I never walk backwards.