Internal execution process of BeanDefinitionRegistryPostProcessor of Spring source code

Spring provides many extended interfaces, including a BeanDefinitionRegistryPostProcessor interface, which is a sub-interface of BeanFactoryPostProcessor. This interface is extremely important, because there is a class in Spring that inherits this interface and this class is responsible for packet scanning. In the spring source code, the class that implements the BeanDefinitionRegistryPostProcessor interface is processed first. Let's see how it is processed in the source code.

Come to the refresh method of the most critical initialization container in spring, find the invokeBeanFactoryPostProcessors method, which is responsible for processing BeanDefinitionRegistryPostProcessor (package scanning is handled here) and its parent interface BeanFactoryPostProcessor.

Keep clicking in to the invokeBeanFactoryPostProcessors method, you can find that this method has two parameters:

Beanfactory is the bean factory object of spring, and what is the second parameter List<BeanFactoryPostProcessor>? Where did it come from?

Before talking about this parameter, let's talk about the three ways of adding Bean management in spring:

  1. Manually add to the spring container through the api
  2. Add annotations so that spring can package scans to the corresponding classes and add them to the container
  3. Classes in spring, written in spring source code, added to spring container

 The first is to manually add Beans to the spring container through api methods such as addXXX. This method is less used. The second is to add @Component annotations to allow spring to scan these classes through package scans and add them to spring. In the container, the third type is that some Beans written in spring's internal source code are added to the spring container. For example, when spring is just initialized, 5 ground-breaking bds have been added to bdMap.

Speaking of the above parameter, in fact, this object is the object passed in by our developers through the api, such as the following:

Above, manually add a class that inherits the BeanDefinitionRegistryPostProcessor interface through the ApplicationContext object, so that the object will be passed to the second parameter. Spring first processes the manually added class and executes its corresponding method

At the beginning, a few collection classes were created. Through the following code logic, you can know what these collections are (as noted in the figure above). First traverse the manually added list collection to determine whether it is BeanDefinitionRegistryPostProcessor or BeanFactoryPostProcessor. If it is BeanDefinitionRegistryPostProcessor, execute its postProcessBeanDefinitionRegistry method.

The following is to find the bd of the BeanDefinitionRegistryPostProcessor class from the bdMap three times, and each found class will execute its postProcessBeanDefinitionRegistry method.

Finding from bdMap for the first time:

Before this method is executed, spring has manually stored 5 bd in spring's bdMap, of which there is an extremely important bd, which is implemented by the class described by the bd (ConfigurationClassPostProcessor, not detailed here on the details of this class package scan) The interface of BeanDefinitionRegistryPostProcessor is used, and this class is responsible for processing the function of packet scanning. Therefore, the bd of the class that implements the BeanDefinitionRegistryPostProcessor interface obtained from bdMap for the first time is the ConfigurationClassPostProcessor, and the package scanning process can be completed by executing the postProcessBeanDefinitionRegistry method rewritten by this class (the so-called package scanning process is to be @Component, @Controller, @Service, @Repository these annotation classes become corresponding bd and then added to bdMap ), of course, among the scanned classes, there may also be our own classes that implement the inherited BeanDefinitionRegistryPostProcessor interface. So after processing these BeanDefinitionRegistryPostProcessor classes for the first time, bdMap may change, and then continue to look for BeanDefinitionRegistryPostProcessor for the second time.

 The second time is to find the bd corresponding to the class that implements the BeanDefinitionRegistryPostProcessor interface from bdMap, and then traverse these bd and find the bd that has not been executed and also implements the Ordered interface class, and continues to execute its rewritten postProcessBeanDefinitionRegistry method, also That is to say, it is better to scan the class of our own inherited BeanDefinitionRegistryPostProcessor interface after the first package scan is completed. At this time, there will be bd corresponding to our class in bdMap, and then it will be from bdMap when searching for the second time. Find the bd corresponding to the class, if the class implements the Ordered interface, it can be executed postProcessBeanDefinitionRegistry method.

The last and third search is to continue searching in the bdMap after the second search. If the bdMap continues to have a new BeanDefinitionRegistryPostProcessor added during the second search, then the third search It will continue to find the bd corresponding to the class that implements the BeanDefinitionRegistryPostProcessor interface from the bdMap. The while loop is to continue to see if there is a bd corresponding to the class that implements the BeanDefinitionRegistryPostProcessor interface after each search.

 After searching for the corresponding bd of the class that implements BeanDefinitionRegistryPostProcessor after the above three times (the third search may have multiple searches), the registryProcessors collection at this time contains all the found instances that implement BeanDefinitionRegistryPostProcessor, and execute invokeBeanFactoryPostProcessors. Then you can execute the postProcessBeanFactory method found to implement the parent class interface (BeanFactoryPostProcessor) of the instance of BeanDefinitionRegistryPostProcessor. When invokeBeanFactoryPostProcessors is executed, the postProcessBeanFactory method of BeanFactoryPostProcessor manually added through the api can be executed.

Finally, the above is just a simple source code to see how the processing flow of BeanDefinitionRegistryPostProcessor is. If you are not clear about the spring management bean process, you may not understand this article only, you need to know what BeanDefinition ( bd), and how spring performs packet scanning. And why does spring need to process the post-processor BeanDefinitionRegistryPostProcessor first? Because this post processor can expose the access entry of bdMap, the post processor can be used to manually add or delete bd in bdMap, so the class that implements this interface (ConfigurationClassPostProcessor inside spring) scans after the package scan The arrived class becomes the corresponding bd, and then the bd is put into the bdMap, so processing the interface class first is an entry point for managing all Beans.

Guess you like

Origin blog.csdn.net/weixin_37689658/article/details/106689090