An overview,
BeanFactoryPostProcessor is an important interface to extend spring container functions, such as modifying bean attribute values and implementing bean dynamic proxy. Many frameworks realize the extension of the Spring container through this interface. For example, when Mybatis integrates with Spring, only mapper interface is defined without implementation class, but Spring can complete automatic injection. How to realize these, this article will explore.
Distinguish between:
- BeanPostProcessor: bean post-processor that intercepts bean-created objects before and after initialization
- Spring BeanFactoryPostProcessor: The beanFactory post-processor is called after the beanFactory standard has been initialized. At this point, all bean definitions have been saved and loaded into the beanFactory, but the bean instance has not been created. At this point, the bean properties can be modified and extended
Ii. Case analysis
/ / start the class
@Test
public void TestMain(a) {
// Create an IOC container
new AnnotationConfigApplicationContext(AppConfig.class);
}
// The bean to inject
public class User {
public User(a){
System.out.println("user create"); }}/ / configuration class
@ComponentScan("config")
@Configuration
public class AppConfig {
@Bean
public User user(a){
return newUser(); }}// BeanFactoryPostProcessor implementation class
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor#postProcessBeanFactory");
int count = configurableListableBeanFactory.getBeanDefinitionCount();
String[] names = configurableListableBeanFactory.getBeanDefinitionNames();
System.out.println("Currently in the BeanFactory" + count + "个Bean"); System.out.println(Arrays.asList(names)); }}Copy the code
Run to start the class, you can see, by getting into the container components, found in beans created before execution MyBeanFactoryPostProcessor postProcessBeanFactory method, thus it can be seen that in the instance of the bean is not created, That is, BeanFactoryPostProcessor is called before initialization, so you can extend the functionality here and modify the bean’s properties.
Third, source code analysis
We use the Debug method to view the method call chain step by step, and set a breakpoint on the postProcessBeanFactory method. Debug runs the start class:
As you can see, entered the refresh () method of invokeBeanFactoryPostProcessors method, that is to say, in invokeBeanFactoryPostProcessors method is executed in the rear of the beanFactory handler method.
public void refresh(a) throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
......
// The beanFactory afterprocessor is executed in this method
this.invokeBeanFactoryPostProcessors(beanFactory); . }}Copy the code
To the next method, to invokeBeanFactoryPostProcessors# invokeBeanFactoryPostProcessors method,
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {... sortPostProcessors(regularPostProcessors, beanFactory);// execute PostProcessor that implements PriorityOrdered interface
invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList(registryProcessors.size());
Iterator var21 = registryProcessors.iterator();
while(var21.hasNext()) {
String postProcessorName = (String)var21.next();
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
// Execute the PostProcessor that implements the Ordered interface
invokeBeanFactoryPostProcessors((Collection)orderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList(currentRegistryProcessors.size());
Iterator var24 = currentRegistryProcessors.iterator();
while(var24.hasNext()) {
ppName = (String)var24.next();
// Get the BeanFactoryPostProcessor name for each PostProcessor from the bean factory
nonOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
// Execute the beanFactory PostProcessor (last execute the normal interface PostProcessor)
invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
beanFactory.clearMetadataCache();
}
Copy the code
As you can see, in this method, is to call the bottom invokeBeanFactoryPostProcessors method performs the beanFactory post processor, ask questions:
How do we find the PostProcessor and implement their methods?
[1] Get PostProcessor
Code above respectively carried out three kinds of interface BeanFactoryPostProcessors, before execution, on the PostProcessor for processing, as follows, separate three PostProcessor placed:
- PriorityOrderedPostProcessors: place a prioritization of the interface
- PostProcessorNames orderedPostProcessorNames: place a sort
- Place ordinary PostProcessorNames nonOrderedPostProcessorNames:
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {...for(int var10 = 0; var10 < var9; ++var10) {
ppName = var8[var10];
/ / will have priority interface in priorityOrderedPostProcessors
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
There will be sorting interface in orderedPostProcessorNames / /
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
} else {
/ / put the common interface in nonOrderedPostProcessorNamesnonOrderedPostProcessorNames.add(ppName); }}... }Copy the code
Now we’ve got the PostProcessor, the PriorityOrdered interface, the Ordered interface, the normal interface, and then we’re going to iterate, and we’re going to implement the normal interface, Get the BeanFactoryPostProcessor name for each PostProcessor from the Bean factory
[2] Iterate through and execute PostProcessor
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
StartupStep var10000 = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process");
postProcessor.getClass();
StartupStep postProcessBeanFactory = var10000.tag("postProcessor", postProcessor::toString); postProcessor.postProcessBeanFactory(beanFactory); postProcessBeanFactory.end(); }}Copy the code
Iterate through each PostProcessor, calling back to the postProcessBeanFactory method for each.
Four,
- Refresh () : the IOC container creates objects
- BeanFactoryPostProcessors invokeBeanFactoryPostProcessors () : perform, i.e. the beanFactory post processor
- Direct all types are found in the BeanFactory BeanFactoryPostProcessors components, and perform their methods
- Through the source code as you can see, the initialization is in other components (finishBeanFactoryInitialization) before execution