PostProcessor

Why do you want to have this post processor this interface, understand the Spring container friend should know that all the ApplicationContext needs to call AbstractApplicationContext# refresh method, it is a template method, Since you are using the template method design pattern, you should provide hooks, which are hook functions. PostProcessor was designed to fulfill this custom extension requirement.

UML

  • BeanPostProcessor

  • BeanFactoryPostProcessor

PostProcessor overview

BeanFactoryPostProcessor

Container level post-processor with only one method declared inside. Spring calls the post-processor in the order it is declared, and BeanFactoryPostProcessor hands the container itself over to the interface implementation classes during container initialization. Once you get the container, you can do a lot of customization.

@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * 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
BeanDefinitionRegistryPostProcessor

From the annotation container parsing BeanDefinition chapter, you’ll learn BeanDefinitionRegistryPostProcessor is a special kind of Spring BeanFactoryPostProcessor, but Spring will give priority to deal with this kind of post processor, Some of the spring BeanFactoryPostProcessor reprocessing routine. This can be interpreted as a VIP BeanFactoryPostProcessor, which takes precedence over the regular BeanFactoryPostProcessor. A dedicated post-registration processing method is also declared internally. postProcessBeanDefinitionRegistry

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * 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

BeanPostProcessor

You can implement BeanPostProcessor to affect the life cycle of all beans, including pre – and post-initialization processing. You’ll come across the BeanPostProcessor later in the life cycle of Spring beans

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

Use postProcessor

MyBeanFactoryPostProcessor

  • Based on the object
@Data
public class Root {

	private String name;

	private String description;

	private boolean isRoot;
}
Copy the code
  • The BeanDefinition is injected into the container through a post-processor
package com.xjm.bean.postprocessor;

import com.xjm.model.Root;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.annotation.Configuration;

/ * * *@author jaymin
 * 2021/1/7 23:10
 */
@Configuration
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}/** * Modifies the internal BeanDefiniton registry of the application context after standard initialization. <br> * All regular bean definitions will be loaded, but no beans have been instantiated yet. <br> * This allows more Beandeinitions to be added before the next post-processing phase begins. < br > * Spring factory level of Spring BeanFactoryPostProcessor, priority level is higher than conventional Spring BeanFactoryPostProcessor. < br > * integrate third-party framework, You can implement this registration interface for BeanDefinition registration. Such as Mybatis.<br> * Design pattern: Chain of responsibility pattern < BR > *@param registry the bean definition registry used by the application context
	 * @throws BeansException
	 */
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		BeanDefinition beanDefinition = getBeanDefinition(Root.class);
		registry.registerBeanDefinition("root",beanDefinition);
		System.out.println("Customer BeanPostProcessors execute.");
	}

	private BeanDefinition getBeanDefinition(Class
        clazz){
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz).getBeanDefinition();
		returnbeanDefinition; }}Copy the code
  • test

@ComponentScan based on its own package path to modify, here the program is running properly, indicating that Root is registered in the container.

@Configuration
@ComponentScan(value = "com.xjm")
public class BeanDefinitionDemoByAnnotation {
	public static void main(String[] args) {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextDemo.class);
		Root root = applicationContext.getBean("root", Root.class); }}Copy the code

MyBeanPostProcessor

Simply implement BeanPostProcessor by observing the scope of its behavior.

@Configuration
public class MyBeanPostProcessor implements BeanPostProcessor {

	@Override
	@Nullable
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println(beanName + " invoking MyBeanPostProcessor#postProcessBeforeInitialization");
		return bean;
	}

	/** * all beans can be operated uniformly *@param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return
	 * @throws BeansException
	 */
	@Override
	@Nullable
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println(beanName + " invoking MyBeanPostProcessor#postProcessAfterInitialization");
		returnbean; }}Copy the code
  • result

As you can see, the implementation of MyBeanPostProcessor affects the initialization of all beans.

conclusion

  • The post-processor is the extensibility hook interface that Spring leaves for developers.
  • From the rear processor, it can be briefly divided into:BeanFactoryPostProcessorandBeanPostProcessorAmong them,BeanFactoryPostProcessorYou can manipulate containers,BeanPostProcessorAffects the life cycle of all beans.
  • BeanDefinitionRegistryPostProcessorIt’s a special kind ofBeanFactoryPostProcessorIs superior to otherBeanFactoryPostProcessorThe execution.

Further reading

Spring BeanPostProcessor Spring BeanPostProcessor Spring BeanPostProcessor