1 使用
示例:去除Spring容器中潜在的敏感词信息,例如bean定义中过滤"zxt"、"sb"等词。
1.1 XML文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="customBeanFactoryPost" class="com.test.CustomBeanFactoryPostProcessor">
<property name="obs">
<set>
<value>zxt</value>
<value>sb</value>
</set>
</property>
</bean>
<bean id="u1" class="com.test.UserPO" >
<property name="userName" value="sb" />
<property name="email" value="zxt@163.com" />
<property name="address" ref="testAddr" />
</bean>
<bean id="testAddr" class="com.test.Address" >
<property name="desc" value="testDesc" />
<property name="detail" value="testDetail" />
</bean>
</beans>
1.2 POJO:UserPo
public class UserPO {
private String userName;
private String email;
private Address address;
// setter, getter
}
public class Address {
private String desc;
private String detail;
// setter, getter
}
1.3 BeanFactoryPostProcessor
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private Set<String> obs;
public CustomBeanFactoryPostProcessor() {
obs = new HashSet<>();
}
/// 数据解析
private StringValueResolver valueResolver = (strVal) -> {
if (obsContainValue(strVal)) {
return "******";
}
return strVal;
};
//将所有bean 的参数中含有 obs 集合中的值进行屏蔽
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
visitor.visitBeanDefinition(bd);
}
}
private boolean obsContainValue(String value) {
String strValue = value.toLowerCase();
return this.obs.contains(strValue);
}
public void setObs(Set<String> obs) {
this.obs.clear();
for (String ob : obs) {
this.obs.add(ob.toLowerCase());
}
}
}
1.4 测试
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("custom-post.xml");
UserPO userPO = (UserPO) ac.getBean("u1");
System.out.println(userPO);
}
2 源码分析
2.1 简介
BeanFactoryPostProcessor
是在AbstractApplicationContext
扩展中实现的。在Spring容器实例化Bean之前的操作,是一个容器级别的处理器。
在Spring中使用的${userName}
的引用变量就是通过BeanFactoryPostProcessor
实现的,即PropertyPlaceholderConfigurer
。
2.2 源码
AbstractApplicationContext#refresh()
方法中,会获取beanFactory
的所有BeanFactoryPostProcessor
并进行调用
public void refresh() throws BeansException, IllegalStateException {
// 执行BeanFactory中的所有BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
执行BeanFactoryPostProcessor
委托给了PostProcessorRegistrationDelegate
类来实现。
对于BeanFactoryPostProcessor
的处理分为2种情况:
- 特殊的BeanDefinitionRegistryPostProcessor
- 常规的BeanFactoryPostProcessor
无论是哪种情况,都需要考虑两种情况:
硬编码注册后置处理器
硬编码注册的后处理器主要通过:AbstractApplicationContext#addBeanFactoryPostProcessor()
- 通过配置注入的后置处理器
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 记录通过硬编码方式注册的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
// 记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
// 获取所有通过配置文件注入的BeanDefinitionRegistryPostProcessor类
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 1.执行实现PriorityOrdered的所有BeanDefinitionRegistryPostProcessor
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);
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// 2.执行实现Ordered的所有BeanDefinitionRegistryPostProcessor
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);
// 3.执行其他所有的BeanDefinitionRegistryPostProcessor
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;
}
}
}
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 获取所有配置注入的BeanFactoryPostProcessor,并执行
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
} else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
} else {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}