PostProcessor is the rear processor
PostProcessor is itself a Bean that needs to be registered with the container:
- Its methods are called by the container at certain times
- Implement extensions to beans without changing the container or Bean core logic
- Packaging beans, affecting their behavior, modifying the contents of beans, and so on
Classes are divided into container level postprocessors and Bean level postprocessors:
- BeanDefinitionRegistryPostProcessor
- BeanFactoryPostProcessor
- BeanPostProcessor
BeanDefinitionRegistryPostProcessor
Allow registered before the start of the normal spring BeanFactoryPostProcessor detection more custom beandefinition, so you can write an interface implementation class to realize BeanDefinitionRegistryPostProcessor, Register additional BeanDefinition instances in the container
On the analysis of resource location, loading, before parsing, registration link, AbstractApplicationContextrefresh()
Method is calledinvokeBeanFactoryPostProcessors(beanFactory);
To execute the container-level post-processorThis interface inheritsBeanFactoryPostProcessor
, so it is also a special BeanFactoryPostProcessor. There is a single method that needs to create an instance of BeanDefinition in the body of the method, and then register the BeanDefinition object with the registry object passed in.
Follow the above ideas, you can create a new postprocessor package, and create a custom class that achieve BeanDefinitionRegistryPostProcessor.
package com.wjw.postprocessor;
import com.wjw.entity.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomizedBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Class<? > clazz = User.class;// To create an instance of BeanDefinition
BeanDefinitionBuilder builder =BeanDefinitionBuilder.genericBeanDefinition(clazz);
// Create a BeanDefinition instance
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
registry.registerBeanDefinition("user5", definition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}}Copy the code
Then try to get the bean named User5 in the program entry We can load third party beans in this post-processor to reuse their power (Mybatis)
BeanFactoryPostProcessor
Since BeanDefinitionRegistryPostProcessor BeanDefinition instance if it’s the custom registration, the remaining two rear processing effect is mainly influence the behavior of the container.
The interface also has only one method, which is inrefresh()
In the methodinvokeBeanFactoryPostProcessors
Method to be executed.
BeanPostProcessor
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
returnbean; }}Copy the code
The interface consists of two callback methods that BeanPostProcessor gets from the container for each bean instance created with the container before the call container initializes and after any bean initializes the callback.
Example:
package com.wjw.postprocessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomizedBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{
System.out.println(beanName + "----- postProcessBeforeInitialization() ");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException{
System.out.println(beanName + "----- postProcessAfterInitialization() ");
returnbean; }}Copy the code
Can use BeanPostProcessor ability to implement packaging of beans, namely after the bean created is postProcessAfterInitialization method in the bean packaging some common logic, such as log statistics related to uniform to do some time consuming, After enhancing the behavior, return the bean.
How does the container call methods in the post-processor in time to process it? To go back to the previous refresh methods invokeBeanFactoryPostProcessors method, to enter
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
Copy the code
Analyze it.
Since the container supports the registration of multiple Postprocessors, the execution must be distinguished according to the priority. This is also the reason why the postprocessors are distinguished according to priorityOrder and Order. When executing these Postprocessors one by one, the responsibility chain mode in the design mode is adopted
private static void invokeBeanDefinitionRegistryPostProcessors( Collection
postProcessors, BeanDefinitionRegistry registry) {
for(BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); }}Copy the code
Each recipient contains a reference to another recipient, and if an object cannot handle the request, the same request is forwarded to the next recipient, and so on.