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
- From the comments in the source code:
refresh
The 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. - A diagram of the Spring context is provided to give you an idea of the structure
- From the comments in the source code:
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
- Project entry (Entry to start the Spring environment)
- Fully configured class that defines the package to scan
- Manually add BeanDefinitionRegistryPostProcessor
- Manually added BeanFactoryPostProcessor
- By the spring scan BeanDefinitionRegistryPostProcessor but not Ordered and PriorityOrdered interface
- By spring scan out BeanDefinitionRegistryPostProcessor Ordered interface is achieved, and the weight of 1 = > low weight, priority is carried out
- By spring scan out BeanDefinitionRegistryPostProcessor Ordered interface is achieved, and the weight for the 2 = > weight low, priority is carried out
- By spring scan out BeanDefinitionRegistryPostProcessor PriorityOrdered interface is achieved, and the weight of 1 = > low weight, priority is carried out
- By spring scan out BeanDefinitionRegistryPostProcessor PriorityOrdered interface is achieved, and the weight for the 2 = > weight low, priority is carried out
- BeanFactoryPostProcessor scanned by Spring
- The BeanFactoryPostProcessor scanned by Spring implements the Ordered interface, and the lower the weight is, the higher the priority is
- The BeanFactoryPostProcessor scanned by Spring implements the Ordered interface, and the lower the weight is, the higher the priority is
- BeanFactoryPostProcessor scanned by Spring implements a PriorityOrdered interface. The lower the weight is, the higher the priority is
- 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.