[Source code analysis] Spring source code interpretation-beanFactory and Bean’s post-processor process


In the previous article, we introduced in detail how spring successfully created beanfactory by loading the xml configuration file. Following the core process, we continue to talk about the post-processing process of beanFactory and Bean.

 //Template method left to subclasses, allowing subclasses to continue to perform some processing on the factory; Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//[Big Core] Factory Enhancement: Execute all BeanFactory post-enhancers; use BeanFactory post-enhancers to modify or enhance the factory, and the configuration class will be parsed here. Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

//[Core] Register all Bean post-processors Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();

postProcessBeanFactory

The invokeBeanFactoryPostProcessors method is the core, and the main method is to obtain all subclasses of beanFactoryPostProcessors.

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {<!-- -->
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); //Execute all factory enhancers
//The above class is called: Post-processor registration agent (facade mode-decoration mode)
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (!NativeDetector.inNativeImage() & amp; & amp; beanFactory.getTempClassLoader() == null & amp; & amp; beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {<!-- -->
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}

The core method is invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {<!-- -->

Set<String> processedBeans = new HashSet<>();

if (beanFactory instanceof BeanDefinitionRegistry) {<!-- -->
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//First get the underlying BeanFactoryPostProcessor by default
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {<!-- -->
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {<!-- -->
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {<!-- -->
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First: Get all BeanDefinitionRegistryPostProcessors that implement PriorityOrdered interface from the factory; First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); //Get the BD information of each component in the system and compare the types to see if they match the specified type
for (String ppName : postProcessorNames) {<!-- -->
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {<!-- -->
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//Get this component [getBean entire component creation process] from the factory and put it in this collection
processedBeans.add(ppName);
}
} //Use priority sorting below
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()); //Execute these BeanDefinitionRegistryPostProcessors
currentRegistryProcessors.clear();

// Next, obtain all BeanDefinitionRegistryPostProcessors that implement the Ordered interface. Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {<!-- -->
if (!processedBeans.contains(ppName) & amp; & amp; beanFactory.isTypeMatch(ppName, Ordered.class)) {<!-- -->
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName); //Even if PriorityOrdered and Ordered are implemented, PriorityOrdered
}
}//Sort
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()); //Execution
currentRegistryProcessors.clear();

// Finally, our custom interface generally does not have any priority and sorting. Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {<!-- -->
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);//Get all BeanDefinitionRegistryPostProcessor
for (String ppName : postProcessorNames) {<!-- -->
if (!processedBeans.contains(ppName)) {<!-- -->
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}//Sort, sort according to the case of class names
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear(); //Prevent repeated execution
}

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

else {<!-- -->
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//I was executing BeanDefinitionRegistryPostProcessor before, and I will execute BeanFactoryPostProcessor later.
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);
}
}

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

// Next, invoke the BeanFactoryPostProcessors that implement Ordered. 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 execute BeanFactoryPostProcessor without any priority and ordering interfaces 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); //Execute all BeanFactoryPostProcessors
beanFactory.clearMetadataCache();
}

The main process is actually to first get the underlying BeanFactoryPostProcessor by default, and then get all the BeanDefinitionRegistryPostProcessors that implement the PriorityOrdered interface from the factory. Next, get all the BeanDefinitionRegistryPostProcessor that implement the Ordered interface.

BeanPostProcessors

 protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {<!-- -->
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {<!-- -->

// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate + is:closed + label:"status: + declined"
//Get all BeanPostProcessor in the container; Bean's post-processor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {<!-- -->
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {<!-- --> //Get all BeanPostProcessors that implement PriorityOrdered
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {<!-- -->
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {<!-- -->
orderedPostProcessorNames.add(ppName);
}
else {<!-- -->
nonOrderedPostProcessorNames.add(ppName);
}
}

//First, register the BeanPostProcessors that implement PriorityOrdered; First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

//Next, register the BeanPostProcessors that implement Ordered. Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {<!-- -->
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); //Get the post-processor object
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {<!-- -->
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);

// Finally, register all regular BeanPostProcessors; Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {<!-- -->
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); //Get this component from the container
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {<!-- -->
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

//Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

//Re-register post-processor for detecting inner beans as ApplicationListeners,
// Move it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}