Spring - IoC 容器之拓展点 BeanFactoryPostProcessor

概述

Spring - IoC 容器之拓展点 BeanPostProcessor 这篇文章中讲解了 BeanPostProcessor 的作用和原理,是在 Bean 的初始化前后进行拦截工作。而 BeanFactoryPostProcessor 在功能上有点类似,我们来看一下源码:

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;

}

从源码注释中我们了解到,BeanFactoryPostProcessor 的拦截时机是在 ApplicationContext 的标准初始化之后调用的,可以用来修改 bean definition registry 中的 bean definition 信息,这时候所有的 BeanDefinition 已经加载进 BeanFactory 了,但是还没有初始化。

举例

自定义 BeanFactoryPostProcessor 的实现类:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("invoke my bean post factory post processor.................");
        int beanDefinitionCount = beanFactory.getBeanDefinitionCount();
        System.out.println("当前BeanFactory中有:" + beanDefinitionCount + " 个BeanDefinition");
    }
}
@Configuration
@ComponentScan("com.keke.ext")
// 导入一个 Bean,并自定了初始化方法(参考:https://blog.csdn.net/qiaohao0206/article/details/125876005)
@Import(Car.class)
public class ExtConfig {
}

初始化 IoC 容器,并输出容器中的 Bean

invoke my bean post factory post processor.................
当前BeanFactory中有:7BeanDefinition
car init by @PostConstruct
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
extConfig
myBeanFactoryPostProcessor

从输出结果可以看出,BeanFactoryPostProcessor 的执行时机是在 Bean 的初始化之前调用的,并且这时候 BeanFactory 中已经有了 BeanDefinition

原理

我们来看一下 IoC 容器 AnnotationConfigApplicationContext 的初始化过程:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	this();
	register(componentClasses);
	// 核心流程
	refresh();
}

接着查看 refresh() 方法:

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		...

		try {
			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

			// 这里就是调用 BeanFactoryPostProcessor 的核心流程
			// Invoke factory processors registered as beans in the context.
			invokeBeanFactoryPostProcessors(beanFactory);

			// 这里注册 BeanPostProcessor
			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);

			...

			// 这里是完成初始化 Bean 的流程
			// Instantiate all remaining (non-lazy-init) singletons.
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			finishRefresh();
		}
		...
	}
}

查看 invokeBeanFactoryPostProcessors() 方法:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		// 核心流程
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		...
	}

接着查看 PostProcessorRegistrationDelegate 中的 invokeBeanFactoryPostProcessors() 方法:

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

	...

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let the bean factory post-processors apply to them!
	String[] postProcessorNames =
			// 1、这里获取所有类型为 BeanFactoryPostProcessor 的 Bean
			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

	// 2、排序并调用

	// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

	// Finally, invoke all other BeanFactoryPostProcessors.
	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	// 3、核心流程
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
	
	...
}

查看 invokeBeanFactoryPostProcessors() 方法:

private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

	for (BeanFactoryPostProcessor postProcessor : postProcessors) {
		// 执行具体的 postProcessBeanFactory 流程
		postProcessor.postProcessBeanFactory(beanFactory);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值