Other extensions can be found in previous articles:
1. In-depth understanding of The Spring IOC extension (1), Custom XML tags
1. BeanFactoryPostProcessor
First say spring BeanFactoryPostProcessor and BeanDefinitionRegistryPostProcessor, first to see spring BeanFactoryPostProcessor:
/**
* 1. Allows for custom modification of an application context's bean definitions,
* adapting the bean property values of the context's underlying bean factory.
*
* 2. <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* 3. <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
* 4. <p>See PropertyResourceConfigurer and its concrete implementations
* for out-of-the-box solutions that address such configuration needs.
*
* 5. <p>A BeanFactoryPostProcessor may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer* /
public interface BeanFactoryPostProcessor {
/**
* 6. Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
Copy the code
This time you’re like, are you fucking kidding me? Look at a ball without Chinese annotation? I don’t give the reason for the annotations is that the original source of someone else’s English annotations have said very clearly what this stuff is doing, you don’t understand the words don’t be afraid, I give you a sentence a good translation, by the way on my own understanding 😊.
Let’s take a look at the most important part of the note, which is the sixth part, and the English translation of these means: Modify the beanFactory object in the ApplicationContext before its standard initialization, at which point all BeanDefinitions should have been loaded, but no beans have been initialized. This method allows you to modify or add beanDefinition properties, and even initialize the bean. Ok, I have finished translating 6. After studying the previous articles, we know that all BeanDefinitions are loaded before the BeanFactoryPostProcessor is implemented. It is not difficult to understand by comparing my translation of the annotations. We can modify the information of the loaded BeanDefinitions. Some of you may still want to have a bean pre-initialized here, but put your bean away, why? Let’s take a look at the comment at 5.
A BeanFactoryPostProcessor may interact with or modify other BeanDefinitions, but it does not interact with beans. Because doing this with beans triggers premature bean initialization, which is an intrusion into the container and can cause side effects, implementing BeanPostProcessor is a good idea if you need to interact with bean instances. Okay, I’m done translating, but you still don’t understand why you can’t initialize here. Let’s look at my following demo:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){ TestBean testBean = beanFactory.getBean(TestBean.class); }}Copy the code
TestBean.java
@Component
@Data
public class TestBean {
@Autowired
private TestBean1 testBean1;
}
Copy the code
TestBean2.java
@Component
public class TestBean1 {}Copy the code
We defined a BeanFactoryPostProcessor, instantiated the TestBean, and started the project, which we can see in the console:
That is, the TestBean is initialized, but its member property is null, because the BeanPostProcessor that injected the property has not been initialized, and the member property remains null until the end, which is what happens with annotations. If you’re using XML, this won’t happen, but don’t do it anyway.
Then we say again BeanDefinitionRegistryPostProcessor, still to look at the code:
/**
* 1. Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* 2. Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
Copy the code
Modify the registration of the BeanDefinition of ApplicationContext after its standard initialization. At this point, all of the normal BeanDefinitions have been loaded but not initialized, so you can add more BeanDefinitions before the next processing phase. Let’s take a closer look at the method parameters here, and then compare the method parameters with the method parameters in BeanFactoryPostProcessor. It’s not hard to find that the parameters of the two methods are different. The BeanDefinitionRegistryPostProcessor BeanDefinitonRegistry method parameters was in there, But the inside of the spring BeanFactoryPostProcessor is ConfigurableListableBeanFactory, through comparing these two parameters, we can come out the conclusion, BeanDefinitionRegistryPostProcessor is to add BeanDefinition and spring BeanFactoryPostProcessor is to modify BeanDefinition properties, in the author’s opinion, These two interfaces are based on the extension framework level, what is called extension based on the framework, I think, in general, when you need to use these two interfaces, that you’re going to be based on the spring framework to extend some things, at this time, you write a class is not used in the business code, and the running of your code, It’s just that during the initialization of the Spring IOC container, none of the business classes are initialized yet. Some extension points, such as when you implement an interface like InitializingBean, the code that implements the interface is likely to be used in the business process. Such extension points can be understood as application-level extensions, and our previous custom XML tags are also framework-based extensions.
We finally see a BeanDefinitionRegistryPostProcessor case, we use mybatis, often using Mapper annotation mark on an interface, then in another class by Autowired annotations to reference, at this time, There’s no implementation class at all, but Autowired can still reference it, Is because the mybatis – spring modules of MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor this interface, Add BeanDefinition to beanFactory
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.registerFilters();
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
Copy the code
This code is the implementation of BeanDefinitionRegistryPostProcessor MapperScannerConfigurer code, the last sentence is the Mapper under scanning basePackage path, And parse to the corresponding BeanDefinition into the Spring container.
2. BeanPostProcessor
BeanPostProcessor BeanPostProcessor is another extended interface provided by Spring. This interface is used to modify information in the bean after it has been created, mainly modifying properties. Let’s look at its code:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
Copy the code
As you can see, there are only two lines of code in there. PostProcessBeforeInitialization with the above method is in the bean is created and initialized before spring call for you, the back method is after bean is created and initialized after spring call for you. A lot of people don’t understand exactly what this is initialized, the initialization refers to: bean in creating good and be populated, but hasn’t done any initialization, in other words you members of the bean properties have been injected, but you may also need the member attribute to do some of the initialization, also didn’t do.
The usage scenarios of this class need to be studied by the readers themselves. I just remind you that, in the author’s opinion, this class is also based on the framework extension, so do not do any business logic operations in the implementation of this class, just like the above BeanFactoryPostProcessor. In this case, The bean in your business code is probably null. If you need to initialize some business logic operation, use another initialization method.