Spring扩展-4-BeanFactoryPostProcessor

330 阅读3分钟

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”