Skip to content

Commit aec8a5d

Browse files
authored
docs(spring): update BeanPostProcessor.md (#124)
1 parent 9e4f4da commit aec8a5d

File tree

1 file changed

+127
-2
lines changed

1 file changed

+127
-2
lines changed

docs/Spring/IoC/BeanPostProcessor.md

+127-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
BeanPostProcessor 接口 也叫 Bean 后置处理器,作用是在 Bean 对象实例化和依赖注入完成后,在显示调用 bean 的 init-method(初始化方法)的前后添加我们自己的处理逻辑。注意是 Bean 实例化完毕后及依赖注入完成后触发的,接口的源码如下。
1+
BeanPostProcessor 接口也叫 Bean 后置处理器,作用是在 Bean 对象实例化和依赖注入完成后,在配置文件 bean 的 init-method(初始化方法)或者 InitializingBean 的 afterPropertiesSet 的前后添加我们自己的处理逻辑。注意是 Bean 实例化完毕后及依赖注入完成后触发的,接口的源码如下。
22

33
```java
44
public interface BeanPostProcessor {
@@ -15,4 +15,129 @@ public interface BeanPostProcessor {
1515
}
1616
```
1717

18-
使用方法也很简单,实现 BeanPostProcessor 接口,然后将实现类注入 IoC 容器即可。
18+
共有两种方式实现:
19+
20+
- 实现 BeanPostProcessor 接口,然后将此类注册到 Spring 即可;
21+
- 第二种是通过`ConfigurableBeanFactory` 的 addBeanPostProcessor 方法进行注册。
22+
23+
BeanPostProcess 可以有多个,并且可以通过设置 order 属性来控制这些 BeanPostProcessor 实例的执行顺序。 仅当 BeanPostProcessor 实现 Ordered 接口时,才能设置此属性,或者 PriorityOrdered 接口。
24+
25+
如果某个类实现了 BeanPostProcessor 则它会在 AbstractApplicationContext 中的 registerBeanPostProcessors(beanFactory)方法中创建 bean 而不是和普通的 bean 一样在 finishBeanFactoryInitialization(beanFactory)中才被创建。
26+
27+
当我们注册 BeanPostProcessor 的时候,其中我省略了大部分无关代码:
28+
29+
```java
30+
public static void registerBeanPostProcessors(
31+
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
32+
// 找到实现BeanPostProcessor接口的子类bean名称
33+
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
34+
// 加一是因为下一行又加了一个BPP(BeanPostProcessor)
35+
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
36+
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
37+
38+
// 排序省略,没啥好讲的,你只需要知道没有实现排序接口的BPP放在了nonOrderedPostProcessorNames这里
39+
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
40+
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
41+
List<String> orderedPostProcessorNames = new ArrayList<>();
42+
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
43+
for (String ppName : postProcessorNames) {
44+
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
45+
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
46+
priorityOrderedPostProcessors.add(pp);
47+
if (pp instanceof MergedBeanDefinitionPostProcessor) {
48+
internalPostProcessors.add(pp);
49+
}
50+
}
51+
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
52+
orderedPostProcessorNames.add(ppName);
53+
}
54+
else {
55+
nonOrderedPostProcessorNames.add(ppName);
56+
}
57+
}
58+
59+
// 中间省略了一些....
60+
61+
// 重点来了
62+
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
63+
for (String ppName : nonOrderedPostProcessorNames) {
64+
// 当它getBean的时候我们的BPP就开始创建
65+
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
66+
nonOrderedPostProcessors.add(pp);
67+
if (pp instanceof MergedBeanDefinitionPostProcessor) {
68+
internalPostProcessors.add(pp);
69+
}
70+
}
71+
}
72+
```
73+
74+
在此我举例一个典型的例子 AutowiredAnnotationBeanPostProcessor,是 BeanPostProcessor 的一个子类,是@Autowired@Value 的具体实现,其他的子类你也可以按如下的流程自行走一边,注意我的例子只是一个最为简单的例子,也就是用@Autowired 注入了一个普通的字段对象
75+
76+
我们看看 AutowiredAnnotationBeanPostProcessor 类,当然也是省略大部分代码:
77+
78+
```java
79+
// 这个类可以看见当我们创建AutowiredAnnotationBeanPostProcessor对象的时候完成了一个工作就是给
80+
// autowiredAnnotationTypes赋值,这个操作有点超前,后面根据这个判断要注入的类中是否有如下的注解
81+
public AutowiredAnnotationBeanPostProcessor() {
82+
this.autowiredAnnotationTypes.add(Autowired.class);
83+
this.autowiredAnnotationTypes.add(Value.class);
84+
try {
85+
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
86+
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
87+
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
88+
}
89+
catch (ClassNotFoundException ex) {
90+
// JSR-330 API not available - simply skip.
91+
}
92+
}
93+
// 从InstantiationAwareBeanPostProcessors继承而来
94+
@Override
95+
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
96+
// 寻找注入的元数据,其中它有注解扫描,和类属性信息的填充
97+
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
98+
try {
99+
// 把数据注入到当前的bean,由于需要分析的过程太多就略过怎么实现的
100+
metadata.inject(bean, beanName, pvs);
101+
}
102+
catch (BeanCreationException ex) {
103+
throw ex;
104+
}
105+
catch (Throwable ex) {
106+
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
107+
}
108+
return pvs;
109+
}
110+
```
111+
112+
BeanPostProcessor 的职责是在 bean 初始化后进行实例的更改,所以我们在普通 bean 实例化的时候就可以看见它的身影 AbstractAutowireCapableBeanFactory 中的 populateBean 就是给 bean 属性填充值,同样我们省略大部分代码:
113+
114+
```java
115+
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
116+
// true 因为我们有InstantiationAwareBeanPostProcessors的实现子类
117+
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
118+
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
119+
120+
PropertyDescriptor[] filteredPds = null;
121+
if (hasInstAwareBpps) {
122+
if (pvs == null) {
123+
pvs = mbd.getPropertyValues();
124+
}
125+
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
126+
// 主要方法
127+
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
128+
if (pvsToUse == null) {
129+
if (filteredPds == null) {
130+
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
131+
}
132+
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
133+
if (pvsToUse == null) {
134+
return;
135+
}
136+
}
137+
pvs = pvsToUse;
138+
}
139+
}
140+
}
141+
```
142+
143+
至此当前的 bean 就实现了@Autowired 的字段注入,整个过程看似简单,但却有诸多细节。

0 commit comments

Comments
 (0)