1.接口概述
Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。同时可以定义多个BeanFactoryPostProcessor,通过设置order属性来确定各个BeanFactoryPostProcessor执行顺序。
看一下它的定义:
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;
}
总结下他的注释:postProcessBeanFactory() 工作与 BeanDefinition 加载完成之后,Bean 实例化之前,其主要作用是对加载 BeanDefinition 进行修改。
在
postProcessBeanFactory()中千万不能进行Bean的实例化工作,因为这样会导致 bean 过早实例化,会产生严重后果,我们始终需要注意的是BeanFactoryPostProcessor是与BeanDefinition打交道的,如果想要与Bean打交道,请使用BeanPostProcessor。
2.源码分析
老规矩,还是从AbstractApplicationContext类的refresh方法看起
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
......
显然,invokeBeanFactoryPostProcessors()方法就是我们的目标了,继续看它的定义
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
......
}
可以看到,实际操作是由PostProcessorRegistrationDelegate去执行的。注意invokeBeanFactoryPostProcessors方法的第二个入参是getBeanFactoryPostProcessors()方法,该方法返回的是applicationContext的成员变量beanFactoryPostProcessors,而该成员变量来自于AbstractApplicationContext.addBeanFactoryPostProcessor方法的调用,是留给业务扩展时用的。
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
让我们再回到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法,看看BeanFactoryPostProcessor是如何被处理的。由于该方法内容较多,分为了好几部分去处理,截取其中我们关心的部分即可:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors){
......
//获取容器中的所有BeanFactoryPostProcessor,并进行存储,
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 分离那些实现了PriorityOrdered,Ordered接口的和没有实现接口的
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
//遍历获得的所有的BeanFactoryPostProcessors
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
//如果是实现了PriorityOrdered接口的话,添加到priorityOrderedPostProcessors之中
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
//如果是实现了Ordered接口的话,添加到orderedPostProcessors之中
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
//剩下的就加到这个nonOrderedPostProcessorNames之中
nonOrderedPostProcessorNames.add(ppName);
}
}
......
// 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));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
}
需要注意的是nonOrderedPostProcessorNames,我们自定义的实现BeanFactoryPostProcessor接口的bean就会在此处被找出来。
最后,所有实现了BeanFactoryPostProcessor接口的bean,都被作为入参调用invokeBeanFactoryPostProcessors方法去处理。
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
3.实战演练
定义User类如下
@Component
public class User {
private String name = "AAA";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
定义BeanFactoryPostProcessor如下:
@Component
public class CustomizeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println(">> BeanFactoryPostProcessor 开始执行了");
String[] names = beanFactory.getBeanDefinitionNames();
for (String name : names) {
if("user".equals(name)){
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.addPropertyValue("name", "BBB");
}
}
System.out.println(">> BeanFactoryPostProcessor 执行结束");
}
}
上述代码的功能很简单,找到名为”user”的bean的定义对象,通过调用addPropertyValue方法,将定义中的name属性值改为”BBB”,这样等名为”user”的bean被实例化出来后,其成员变量name的值就是”BBB”,我们执行测试类
@SpringBootTest
class ApplicationTests {
@Autowired
User user;
@Test
void contextLoads() {
System.out.println(user.getName());
}
}
可以看到控制台输出“BBB”