概述
BeanFactoryPostProcessor 是 Spring针对BeanFactory做的扩展,可以对bean的定义(配置元数据进行处理)。也就是说SpringIoc容器允许BeanFactoryPostProcessor 在容器实际实例化任何其他的bean之前读取配置元数据,并有可能修改它。也就是说,我们根据我们的需要对 BeanDefinition
进行修改。
先看BeanFactoryPostProcessor的使用效果
这是一个《Spring源码深度解析》书中的示例,实现一个BeanFactoryPostProcessor,来修改bean中定义的特定属性值,实现一个“屏蔽” 效果。
bean xml 配置文件
<bean id="bfpp" class="com.at.spring.spring2021.ObscenityRemovingBeanFactoryPostProcessor">
<property name="obscenties">
<set>
<value>bollockes</value>
</set>
</property>
</bean>
<bean id="car" class="com.at.spring.beans.autowire.Car"
p:brand="bollockes" p:price="4500000" scope="singleton" lazy-init="false">
</bean>
ObscenityRemovingBeanFactoryPostProcessor.java
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionVisitor;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.util.StringValueResolver;
import java.util.HashSet;
import java.util.Set;
public class ObscenityRemovingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private Set<String> obscenties;
public ObscenityRemovingBeanFactoryPostProcessor() {
obscenties = new HashSet<>(0);
}
public Set<String> getObscenties() {
return obscenties;
}
public void setObscenties(Set<String> obscenties) {
this.obscenties.clear();
for (String obscenty : obscenties) {
this.obscenties.add(obscenty.toUpperCase());
}
}
public ObscenityRemovingBeanFactoryPostProcessor(Set<String> obscenties) {
this.obscenties = obscenties;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
StringValueResolver valueResolver = new StringValueResolver() {
@Override
public String resolveStringValue(String strValue) {
if (isObscene(strValue)) {
return "********";
}
return strValue;
}
};
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
visitor.visitBeanDefinition(bd);
}
}
public boolean isObscene(Object value) {
String potentialObsenity = value.toString().toUpperCase();
return this.obscenties.contains(potentialObsenity);
}
}
Car.java
public class Car {
private String brand;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Car [brand=" + brand + ", price=" + price + "]";
}
public Car() {
System.out.println("Car 无参构造方法");
}
public Car(String brand, double price) {
System.out.println("Car 有参构造方法");
this.brand = brand;
this.price = price;
}
}
main方法
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans-beanFactoryPostProcessor.xml");
BeanFactoryPostProcessor bfpp = (BeanFactoryPostProcessor) classPathXmlApplicationContext.getBean("bfpp");
System.out.println(classPathXmlApplicationContext.getBean("car"));
}
控制台
Car 无参构造方法
Car [brand=********, price=4500000.0]
通过自定义BeanFactoryPostProcessor实现类,当Car 这个 bean中属性 brand 是 obscenties
定义的字符串时,则使用 “*******” 代替。
扩展点
在Spring容器生命周期过程中,有这样一个处理,invokeBeanFactoryPostProcessors(beanFactory)
, 这里就是加载BeanFactoryPostProcessor
并调用的逻辑所在。
AbstractApplicationContext类
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
// 1. Spring 上下文准备阶段
this.prepareRefresh();
// 2. BeanFactory创建阶段
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 3. BeanFactory准备阶段
this.prepareBeanFactory(beanFactory);
try {
// 4. BeanFactory 后置处理阶段
this.postProcessBeanFactory(beanFactory);
// 5. BeanFactory注册BeanFactoryPostProcessor阶段
this.invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册BeanPostProcessor阶段
this.registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源
this.initMessageSource();
// 8. 初始化自定义事件广播器
this.initApplicationEventMulticaster();
// 9. Spring 应用上下文刷新阶段,由子类实现
this.onRefresh();
// 10. Spring事件监听注册阶段
this.registerListeners();
// 11. 实例化剩余的(非lazy init)的单例bean
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var5) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
this.destroyBeans();
this.cancelRefresh(var5);
throw var5;
}
}
}
注册并调用BeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
PostProcessorRegistrationDelegate 类
具体关键代码含义可以看在源码中添加的注释:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 首先调用 BeanDefinitionRegistryPostProcessors
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
// 判断 beanFactory 是否是 BeanDefinitionRegistry 类型
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); // 提前创建一个集合,用于后边存放
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
// 查找 beanFactory 中存放的 BeanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry); // 执行其中的方法
registryPostProcessors.add(registryPostProcessor); // add 到 registryPostProcessors
}
else {
regularPostProcessors.add(postProcessor); // 不是 BeanDefinitionRegistryPostProcessor 类型,所以add 到 常规的 regularPostProcessors
}
}
// 不要在这里初始化FactoryBeans: 我们需要让所有常规bean保持未初始化状态,以便让bean工厂后处理器应用于它们
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 查找 BeanDefinitionRegistryPostProcessor 类型的bean
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 首先调用使用了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
// 优先进行调用 PriorityOrdered (PriorityOrdered 优先级大于Ordered)
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// 其次调用 Ordered
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registryPostProcessors.addAll(orderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
// 最后调用其他的 BeanDefinitionRegistryPostProcessors
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
registryPostProcessors.add(pp);
processedBeans.add(ppName);
pp.postProcessBeanDefinitionRegistry(registry);
reiterate = true;
}
}
}
// 调用所有的 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 调用所有的 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 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 =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
// 查找使用了实现了 PriorityOrdered 的PostProcessor
if (processedBeans.contains(ppName)) {
// 如果在processedBeans集合中,说明一件在前面的代码中处理过了
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
} // 其次调用 Ordered
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 最后调用没有指定顺序的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor
是 BeanFactoryPostProcessor
的子类,自己添加了postProcessBeanDefinitionRegistry
方法,更加便于对BeanDefinition的扩展。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
总结
- 实现了
BeanFactoryPostProcessor
接口,就可以在spring加载bean的生命周期中,实例化 bean前 可以对BeanDefinition
进行修改或处理。 - 这个地方千万不能对bean进行实例化操作,因为会发生意想不到的结果。来自源码中的注释:but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects.
- 在调用
BeanFactoryPostProcessor
提供的方法时,根据PriorityOrdered
->Order
-> 普通的 这个的顺序来执行postProcessBeanFactory
方法。
参考资料
- https://mp.weixin.qq.com/s/CtGguqqDVSFfRxXfJKPR1w
- http://www.itsoku.com/article/323
- https://my.oschina.net/u/4072299/blog/4433981