preface
InvokeBeanFactoryPostProcessors executes the BeanFactory post processor. If you look at this, you have a question:
- What is BeanFactoryPostProcessor?
- How can BeanfactoryPostProcessor be used?
Know the answer to both questions above, have the knowledge of spring BeanFactoryPostProcessor, deep source then, continue reading invokeBeanFactoryPostProcessors this method.
role
The answer can be found on the official website:
The Spring IoC container allows the BeanFactoryPostProcessor to read configuration metadata and possibly change it before the container instantiates any beans other than the BeanFactoryPostProcessor instance.
The BeanFactoryPostProcessor can also be Ordered using the Ordered interface.
Pay attention to
BeanFactoryPostProcessor operates on BeanDefinition, or metadata. It is also possible to instantiate beans by obtaining the BeanFactory, but this is not recommended on the official website.
The sample
The use of spring BeanFactoryPostProcessor
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// Modify the BeanDefinition information
BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
userComponentBeanDefinition.setLazyInit(true);
// Modify the Bean information
// XXX strongly does not recommend premature instantiation of beans by beanfactory.getBean
UserComponent bean = beanFactory.getBean(UserComponent.class);
bean.setUserName("liuzhihang-01"); }}Copy the code
Create your own BeanFactoryPostProcessor and implement the BeanFactoryPostProcessor interface by adding annotations.
In addition to implementing the BeanFactoryPostProcessor interface, there are other interfaces:
Using BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor inherited spring BeanFactoryPostProcessor, extend the increased postProcessBeanDefinitionRegistry method at the same time. It is possible to operate on a BeanDefinition after it has been registered and before the Bean is instantiated.
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// Modify the BeanDefinition information
BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
userComponentBeanDefinition.setLazyInit(true);
// Modify the Bean information
// XXX strongly does not recommend premature instantiation of beans by beanfactory.getBean
UserComponent bean = beanFactory.getBean(UserComponent.class);
bean.setUserName("liuzhihang-01");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// Register a BeanDefinition
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(OrderComponent.class);
AbstractBeanDefinition orderComponentBeanDefinition = builder.getBeanDefinition();
registry.registerBeanDefinition("orderComponent", orderComponentBeanDefinition); }}Copy the code
Here is a screenshot of the test code:
The OrderComponent class does not add any annotations, and after registering as a BeanDefinition, OrderComponent can be retrieved from the container.
How do I modify field properties
It is not recommended to instantiate beans in BeanFactoryPostProcessor.
You can do this by fetching MutablePropertyValues:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// Modify the BeanDefinition information
BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
userComponentBeanDefinition.setLazyInit(true);
MutablePropertyValues userComponentPropertyValues = userComponentBeanDefinition.getPropertyValues();
userComponentPropertyValues.addPropertyValue("userName"."liuzhihang-02");
// Modify the Bean information
// XXX strongly does not recommend premature instantiation of beans by beanfactory.getBean
// UserComponent bean = beanFactory.getBean(UserComponent.class);
// bean.setUserName("liuzhihang-01");}}Copy the code
invokeBeanFactoryPostProcessors
Now I think I know what BeanFactoryPostProcessor does, and the main purpose of this step is to instantiate all beanFactoryPostProcessors.
Enter the source code:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if(! IN_NATIVE_IMAGE && beanFactory.getTempClassLoader() ==null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }}Copy the code
The spring BeanFactoryPostProcessor getBeanFactoryPostProcessors method to obtain their add. What does that mean?
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors(a) {
return this.beanFactoryPostProcessors;
}
Copy the code
To see the source is directly from beanFactoryPostProcessors get, and how to add?
Container addBeanFactoryPostProcessor method actually call.
Continue reading the key code invokeBeanFactoryPostProcessors:
Notice how long this code is!
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List
beanFactoryPostProcessors)
{
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// Determine whether it is BeanDefinitionRegistry
/ / the debug incoming is DefaultListableBeanFactory found here
/ / DefaultListableBeanFactory BeanDefinitionRegistry is realized
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// Create two lists to store processors
/ / BeanDefinitionRegistryPostProcessor spring BeanFactoryPostProcessor as part of the interface
/ / BeanDefinitionRegistryPostProcessor BeanDefinition additional processing, add BeanDefinition
// See examples for the usage
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
/ / beanFactoryPostProcessors cycles
/ / beanFactoryPostProcessors is to use the API context. AddBeanFactoryPostProcessor added
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
/ / added to registryProcessors BeanDefinitionRegistryPostProcessor to separate
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// Process Bean information
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else{ regularPostProcessors.add(postProcessor); }}// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
/ / the above circulation is to perform BeanDefinitionRegistryPostProcessor we call API to add
/ / execute next Spring's own BeanDefinitionRegistryPostProcessor collection
// Execute first those that implement the PriorityOrdered interface, then Ordered the interface, and finally execute the rest
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
/ / the first step to call BeanDefinitionRegistryPostProcessors it implements PriorityOrdered
/ / when the initialization reader In the registered ConfigurationClassPostProcessor into the container
/ / BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor is realized
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
/ / add bean
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// Just add the name after it to determine who has already executedprocessedBeans.add(ppName); }}/ / sorting
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
/ / loop execution processors postProcessBeanDefinitionRegistry method
// This will have to be looked at carefully
// Debug sees that after this step, another class annotated with @Component is registered in Registry
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
/ / remove
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// Process the Ordered processor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
for (String ppName : postProcessorNames) {
// Only those that are not included are executed, and processedBeans are added after execution
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
/ / same as above
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// Execute the rest
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
for (String ppName : postProcessorNames) {
// Only those that are not included are executed, and processedBeans are added after execution
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.
/ / the above treatment is postProcessBeanDefinitionRegistry is in - > BeanDefinitionRegistryPostProcessor
PostProcessBeanFactory -> In BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// Invoke factory processors registered with the context instance.
/ / not BeanDefinitionRegistry is the BeanFactory direct execution beanFactoryPostProcessors can
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!
// Part 2
/ / it is BeanDefinitionRegistryPostProcessor execution
// Start BeanFactoryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// Execute in order
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
// This is done
} 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.
// Execute that implements 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...
// Clear unnecessary metadata information
beanFactory.clearMetadataCache();
}
Copy the code
The above overall can be divided into two parts:
- Perform BeanDefinitionRegistryPostProcessor interface in two methods: postProcessBeanDefinitionRegistry and postProcessBeanFactory.
- Execute the postProcessBeanFactory method in the BeanFactoryPostProcessor interface.
Take the first part:
- First determine if the passed BeanFactory is BeanDefinitionRegistry
- Declare two sets of List regularPostProcessors to store BeanFactoryPostProcessor. RegistryProcessors used to store BeanDefinitionRegistryPostProcessor
- Circulation beanFactoryPostProcessors, this is the way we use the API spring BeanFactoryPostProcessor added.
- BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry will be executed in the cycle, that is my example that add BeanDefinition demonstration method will be executed.
- Start Spring BeanDefinitionRegistryPostProcessor, processing order for PriorityOrdered, Ordered, and the rest
- Cycle, add the corresponding BeanDefinitionRegistryPostProcessor to the currentRegistryProcessors set and processedBeans set said to have treatment.
- Sort them and add them to the registryProcessors in step 1.
- Call invokeBeanDefinitionRegistryPostProcessors perform all the inside of the Processor postProcessBeanDefinitionRegistry method
- After perform 1 and 2, all postProcessBeanDefinitionRegistry has been performed, But the postProcessBeanFactory method in the two collections (registryProcessors and regularPostProcessors) has not been executed yet. And then it loops.
- Declare two sets of List regularPostProcessors to store BeanFactoryPostProcessor. RegistryProcessors used to store BeanDefinitionRegistryPostProcessor
- If not BeanDefinitionRegistry type, the direct execution of incoming beanFactoryPostProcessors can.
Below is a screenshot of the corresponding code
This is just the first half of this method, the implementation of the BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry and postProcessBeanFactory inside.
Since there are also processors that directly implement the BeanFactoryPostProcessor, let’s start with the BeanFactoryPostProcessor processor. The process is similar.
conclusion
By reading more about invokeBeanFactoryPostProcessors (the beanFactory); This step summarizes the method.
Spring BeanFactoryPostProcessor role
The Main function of BeanFactoryPostProcessor is to modify the BeanDefinition information after the BeanDefinition is registered and before the Bean is initialized.
Spring BeanFactoryPostProcessor implementation called BeanDefinitionRegistryPostProcessor, it can be extra register new BeanDefinition into the container.
Description of the process
- This step mainly deals with BeanFactoryPostProcessor and is divided into two steps.
- Perform BeanDefinitionRegistryPostProcessor interface in two methods: postProcessBeanDefinitionRegistry and postProcessBeanFactory.
- Execute the postProcessBeanFactory method in the BeanFactoryPostProcessor interface.
Related to recommend
- PrepareBeanFactory and postProcessBeanFactory
- Spring source learning 09: Refresh about the process
- Spring source code 08: Register the configuration class