- 前言
- 第一部分 核心实现
- 第 1 章 Spring 整体架构和环境搭建
- 第 2 章 容器的基本实现
- 第 3 章 默认标签的解析
- 第 4 章 自定义标签的解析
- 第 5 章 bean 的加载
- 第 6 章 容器的功能扩展
- 第 7 章 AOP
- 第二部分 企业应用
- 第 8 章 数据库连接 JDBC
- 第 9 章 整合 MyBatis
- 第 10 章 事务
- 第 11 章 SpringMVC
- 第 12 章 远程服务
- 第 13 章 Spring 消息
6.6.2 注册 BeanPostProcessor
上文中提到了 BeanFacotoryPostProcessors 的调用,现在我们来探索下 BeanPostProcessor,但是这里并不是调用,而是注册。真正的调用其实是在 bean 的实例化阶段进行的。这是一个很重要的步骤,也是很多功能 BeanFactory 不支持的重要原因。Spring 中大部分功能都是通过后处理器的方式进行扩展的,这是 Spring 框架的一个特性,但是在 BeanFactory 中其实并没有实现后处理器的自动注册,所以在调用的时候如果没有进行手动注册其实是不能使用的。但是在 ApplicationContext 中却添加了自动注册功能,如自定义这样一个后处理器:
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBean
PostProcessor{
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("====");
return null;
}
... ...
}
在配置文件中添加配置:
<bean class="processors.MyInstantiationAwareBeanPostProcessor"/>
那么使用 BeanFactory 方式进行 Spring 的 bean 的加载时是不会有任何改变的,但是使用 ApplicationContext 方式获取 bean 的时候会在获取每个 bean 时打印出“====”,而这个特性就是在 registerBeanPostProcessors 方法中完成的。
我们继续探索 registerBeanPostProcessors 的方法实现。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class,
true, false);
/*
* BeanPostProcessorChecker 是一个普通的信息打印,可能会有些情况,
* 当 Spring 的配置中的后处理器还没有被注册就已经开始了 bean 的初始化时
* 便会打印出 BeanPostProcessorChecker 中设定的信息
*/
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 +
postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory,
beanProcessorTargetCount));
//使用 PriorityOrdered 保证顺序
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<Bean
PostProcessor>();
//MergedBeanDefinitionPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPost
Processor>();
//使用 Ordered 保证顺序
List<String> orderedPostProcessorNames = new ArrayList<String>();
//无序 BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}else if (isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//第一步,注册所有实现 PriorityOrdered 的 BeanPostProcessor
OrderComparator.sort(priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
//第二步,注册所有实现 Ordered 的 BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
OrderComparator.sort(orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
//第三步,注册所有无序的 BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
//第四步,注册所有 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor,并非
重复注册,
//在 beanFactory.addBeanPostProcessor 中会先移除已经存在的 BeanPostProcessor
OrderComparator.sort(internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
//添加 ApplicationListener 探测器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector());
}
配合源码以及注释,在 registerBeanPostProcessors 方法中所做的逻辑相信大家已经很清楚了,我们再做一下总结。
首先我们会发现,对于 BeanPostProcessor 的处理与 BeanFactoryPostProcessor 的处理极为相似,但是似乎又有些不一样的地方。经过反复的对比发现,对于 BeanFactoryPostProcessor 的处理要区分两种情况,一种方式是通过硬编码方式的处理,另一种是通过配置文件方式的处理。那么为什么在 BeanPostProcessor 的处理中只考虑了配置文件的方式而不考虑硬编码的方式呢?提出这个问题,还是因为读者没有完全理解两者实现的功能。对于 BeanFactoryPostProcessor 的处理,不但要实现注册功能,而且还要实现对后处理器的激活操作,所以需要载入配置中的定义,并进行激活;而对于 BeanPostProcessor 并不需要马上调用,再说,硬编码的方式实现的功能是将后处理器提取并调用,这里并不需要调用,当然不需要考虑硬编码的方式了,这里的功能只需要将配置文件的 BeanPostProcessor 提取出来并注册进入 beanFactory 就可以了。
对于 beanFactory 的注册,也不是直接注册就可以的。在 Spring 中支持对于 BeanPost Processor 的排序,比如根据 PriorityOrdered 进行排序、根据 Ordered 进行排序或者无序,而 Spring 在 BeanPostProcessor 的激活顺序的时候也会考虑对于顺序的问题而先进行排序。
这里可能有个地方读者不是很理解,对于 internalPostProcessors 中存储的后处理器也就是 MergedBeanDefinitionPostProcessor 类型的处理器,在代码中似乎是被重复调用了,如:
for (String ppName : postProcessorNames) {
if (isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}else if (isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}else {
nonOrderedPostProcessorNames.add(ppName);
}
}
其实不是,我们可以看看对于 registerBeanPostProcessors 方法的实现方式。
private void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor>
postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
}
}
可以看到,在 registerBeanPostProcessors 方法的实现中其实已经确保了 beanPostProcessor 的唯一性,个人猜想,之所以选择在 registerBeanPostProcessors 中没有进行重复移除操作或许是为了保持分类的效果,使逻辑更为清晰吧。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论