Important interfaces in Spring

Posted by ericburnard on Tue, 14 Jan 2020 12:32:26 +0100

1. BeanFactoryPostProcessor interface

Official website address: https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/core.html#beans-factory-extension-factory-postprocessors

org.springframework.beans.factory.config.BeanFactoryPostProcessor. The semantics of this interface are similar to those of the BeanPostProcessor, with one major difference: BeanFactoryPostProcessor operates on the bean configuration metadata. That is, the Spring IoC container lets a BeanFactoryPostProcessor read the configuration metadata and potentially change it before the container instantiates any beans other than BeanFactoryPostProcessor instances.

In short, BeanFactoryPostProcessor is similar to BeanPostProcessor, but it is quite different: BeanFactoryPostProcessor is a modification of the Bean factory level, which mainly operates the Bean metadata (BeanDefinition) before the Bean instantiation to achieve the effect of modifying the finally instantiated Bean features; BeanPostProcessor is aimed at the Bean level after the Bean instantiation Operation. Although Bean instances (such as BeanFactory.getBean()) can also be fetched in BeanFactoryPostProcessor and then modified or set values, etc., this leads to premature instantiation violating the standard Bean life cycle, which is not recommended by Spring.

public interface BeanFactoryPostProcessor {

	/**
	 * Bean After loading but without callback before instantiation, you can add some properties here for bean instantiation
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

2. BeanDefinitionRegistryPostProcess interface

Beandefinitionregistrypostprocessor is a sub interface of BeanFactoryPostProcessor, so its calling time is the same as BeanFactoryPostProcessor, and it extends a new interface method:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Bean After loading but without a callback before instantiation, you can add a new BeanDefinition here, and the container will be initialized together.
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

To view the source code calling process, first execute org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry), and then execute org.springframework.beans.factory.config.BeanFactoryPostProcessor.postProcessBeanFactory(ConfigurableListableBeanFactory) method:

org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List)Part of source code

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

	}
}

3. BeanPostProcessor interface

Official website address: https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/core.html#beans-factory-extension-bpp

The BeanPostProcessor interface defines callback methods that you can implement to provide your own (or override the container's default) instantiation logic, dependency resolution logic, and so forth. If you want to implement some custom logic after the Spring container finishes instantiating, configuring, and initializing a bean, you can plug in one or more custom BeanPostProcessor implementations.

In short, BeanPostProcessor is the processor after Bean instantiation. There are only two methods in the province of interface. Their execution time is as follows:

public interface BeanPostProcessor {

	/**
	 * Bean Instantiate but execute before initialization
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 *Bean Instantiate and execute after initialization
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

Spring also provides some sub interfaces of BeanPostProcessor, such as MergedBeanDefinitionPostProcessor, instantiaionawarebeanpostprocessor, and smartinstantiaionawarebeanpostprocessor. These sub interfaces extend some interface methods respectively. Please refer to the previous blog for their execution order and functions Source code analysis of complete Spring Bean life cycle.

4. ImportSelector interface

ImportSelector can be very convenient to introduce external classes into spring container management. For example, you can refer to the third-party jar to your own spring project, and it is very convenient to write Bean instances in the third-party jar for spring management. But it must be implemented by Import annotation Import. The parameter of Import annotation can be a class, an ImportSelector or an importbeandefinitionregister interface. If it is a class, a Bean corresponding to the class will be created into the IOC container. If it is an Import interface, the Bean in the corresponding implementation logic will be loaded into the container. Interface source code:

public interface ImportSelector {

	/**
	 * Return the full Class name of the Class to be imported. You can use @ Import to Import the implementation Class on the Class marked by @ Configuration. spring will instantiate the returned Class as Bean managed
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

}

5. ImportSelectorRegistaror interface

ImportSelectorRegistaror implements the dynamic registration of beans with the help of Import annotation. The difference is that ImportSelector only needs to return the full class name from spring to BeanDefinition, while ImportSelectorRegistaror needs to register BeanDefinition in the container itself. Spring AOP, autoproxyregister, Feign, Ribbon, Mybatis, etc. are all implemented with it.

public interface ImportBeanDefinitionRegistrar {

	/**
	 * Register BeanDefinition to implement dynamic Bean injection
	 */
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);

}
Published 99 original articles, won praise 7, visited 8347
Private letter follow

Topics: Spring Mybatis