一、概述
🤔什么是BeanPostProcessor?
BeanPostProcessor是spring提供的一个扩展接口,可以在Bean的实例化、配置、销毁前后,做一些扩展处理。Spring很多bean的相关操作,都是通过BeanPostProcessor实现的。
BeanPostProcessor是一个基础接口,他还有四个扩展接口:
- InstantiationAwareBeanPostProcessor
- SmartInstantiationAwareBeanPostProcessor
- MergedBeanDefinitionPostProcessor
- DestructionAwareBeanPostProcessor
二、Bean创建 vs BeanPostProcessor
在上一章中,我们梳理的Bean的创建流程,源码中充斥着各种BeanPostProcessor。下图描述了,在Bean创建过程中,都触发了哪些BeanPostProcessor。
结合源码,梳理下创建过程中,BeanPostProcessor是在哪里执行,你可以结合以下代码骨干,对源码进行进一步的分析。 AbstractAutowireCapableBeanFactory.createBean
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation:在doCreateBean执行之前,如果return的不是null,则直接返回这个bean,不会执行doCreateBean了;
- AbstractAutowireCapableBeanFactory.doCreateBean
- AbstractAutowireCapableBeanFactory.createBeanInstance:创建对象实例
- SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors:创建之前调用,可以选择使用哪个构造器
- MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition:实例化之后,注入属性之前,每个BeanDefinition仅执行一次。可以改变RootBeanDefinition,比如可以把@Value/@Autowired注解修饰的属性或方法元数据信息缓存下来,留着后续使用。
- AbstractAutowireCapableBeanFactory.populateBean:注入属性
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation:在真正注入属性之前调用,返回false则停止注入,直接返回
- InstantiationAwareBeanPostProcessor.postProcessProperties,在属性注入前执行,可以修改或者校验属性。PS:AutowiredAnnotationBeanPostProcessor,在这里对Autowired的属性进行注入。
- InstantiationAwareBeanPostProcessor.postProcessPropertyValues:已经被标记废弃,建议使用postProcessProperties替代。
- AbstractAutowireCapableBeanFactory.initializeBean:初始化Bean
- AbstractAutowireCapableBeanFactory.invokeAwareMethods:为实现BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的Bean,注入BeanName/ClassLoader/BeanFactory等属性。
- BeanPostProcessor.postProcessBeforeInitialization:初始化之前调用。
- 除上一步的三个Aware接口外,其余的Aware也是在这里处理的
- 被@PostConstruct修饰的方法调用,也是通过该接口实现的
- AbstractAutowireCapableBeanFactory.invokeInitMethods:执行初始化方法,包括
- 实现InitializingBean接口的afterPropertiesSet方法
- xml或者@Bean注解配置的init-method方法
- BeanPostProcessor.postProcessAfterInitialization:初始化之后执行。Spring AOP功能,大部分场景,就是在这里,对bean进行代理的。
- AbstractAutowireCapableBeanFactory.registerDisposableBeanIfNecessary:注册销毁方法
- DisposableBeanAdapter.hasApplicableProcessors
- DestructionAwareBeanPostProcessor#requiresDestruction:判断给定的Bean示例,是否需要该BeanPostProcessor销毁。
- DisposableBeanAdapter.hasApplicableProcessors
- AbstractAutowireCapableBeanFactory.createBeanInstance:创建对象实例
🤔getEarlyBeanReference呢?
是不是感觉哪里不对,getEarlyBeanReference方法呢,看doCreateBean方法时,好像是看到了该方法的调用。
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
以上代码来自于doCreateBean方法,确实出现了getEarlyBeanReference,然而,是被作为lambda表达式中调用的。也就是说,这里并不会调用。
那getEarlyBeanReference在哪里调用呢?
是在调用BeanFactory的getBean方法时,尝试从缓存中,获取单例Bean的时,如果出现了循环依赖,需要提前获取Bean时,才会调用。这也是八股文,spring如何解决循环依赖的核心代码。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
三、其他BeanPostProcessor方法
还有些其他的BeanPostProcessor的方法,在Bean创建的过程中,并不会应用到。
- SmartInstantiationAwareBeanPostProcessor#predictBeanType : 官方的注释为,预测该处理器的postProcessBeforeInstantiation回调函数最终返回的bean的类型。在BeanFactory的getType方法中,会被调用到。不太清除哪里会使用到。
- MergedBeanDefinitionPostProcessor#resetBeanDefinition :Bean的定义信息被重置(删除或者替换)时,需要重置缓存的BeanDefinition的元数据信息。MergedBeanDefinitionPostProcessor的另一个方法为postProcessMergedBeanDefinition,仅一个BeanDefinition仅执行一次,部分的postProcessMergedBeanDefinition实现类通过该方法缓存Bean的元数据信息,如果定义被删除或者替换,则也需要删除相关的元数据信息,否则还会使用旧的元数据信息。
- DestructionAwareBeanPostProcessor#postProcessBeforeDestruction : 在Bean的销毁方法前执行,@PreDestroy就是
InitDestroyAnnotationBeanPostProcessor通过该方法实现的。
四、如何注册
🤔实现了BeanPostProcessor,如何注册到ApplicationContext中呢
只要注册为Bean(无论使用哪种手段),会被自动识别为BeanPostProcessor,当然也可以手动直接调用BeanFactory.addBeanPostProcessor来添加BeanPostProcessor。具体代码都在PostProcessorRegistrationDelegate.registerBeanPostProcessors中
。
注意 乍一看,这里的代码好乱,貌似可以稍微优化一下,不过代码里特意注释了一下,不要瞎改这里的代码,写的这么乱是有原因的。BeanPostProcessor需要按照一定的顺序,分批实例化,再注册到BeanFactory中,顺序如下
- 实现了PriorityOrdered接口的BeanPostProcessor。
- 实现了Ordered接口的BeanPostProcessor。
- 其他BeanPostProcessor。
不可以不按照顺序实例化(调用getBean)、注册到BeanFactory。因为BeanPostProcessor,也是一个Bean,在实例化时,也应该被BeanPostProcessor处理,也就是说,实现了Ordered(且没实现PriorityOrdered)接口的BeanPostProcessor,应该被实现了PriorityOrdered的BeanPostProcessor进行处理。而PriorityOrdered这个接口,一般也是spring内部使用的,用于标识一些比较重要的实现类,优先实例化并注册到BeanFactory中,以处理其他Bean。
从源码中可以看到,@Order注解在这里没有被使用到,是无效的,BeanPostProcessor接口的注释中,也提到了这一点。
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
// 理论上,在BeanPostProcessor的注册过程中,不该有BeanPostProcessor以外类型实例化,BeanPostProcessorChecker就是负责检查这种情况,如果出现,就打印info日志
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest. 把BeanPostProcessor的名字分成三类,实现PriorityOrdered、实现Ordered的和其他
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
// 最后,把实现了MergedBeanDefinitionPostProcessor的,重新注册,放在最后,保证最后运行
// 重复调用addBeanPostProcessor也没关系,会先移除,在加进去
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// 重新注册ApplicationListenerDetector,保证在最后,这样ApplicationListenerDetector才能获取到最终被代理过的Bean
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
五、应用
Spring内部就使用BeanPostProcessor实现了很多功能。
ApplicationContextAwareProcessor- 通过BeanPostProcessor#postProcessBeforeInitialization方法实现了例如 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware等aware接口的支持,不过这个不是在registerBeanPostProcessors方法中统一注册的,而是在之前的prepareBeanFactory方法中,就硬编码注册了,这样保证最先注册,可以保证其他的Bean都被ApplicationContextAwareProcessor处理。AutowiredAnnotationBeanPostProcessor- 实现了对@Autowired/@Value/@Lookup/@Inject注解的支持;CommonAnnotationBeanPostProcessor- 实现了对例如@Resource这样的JSR-250注解的支持;InitDestroyAnnotationBeanPostProcessor实现了对@PostConstruct & @PreDestroy 注解的支持,另外CommonAnnotationBeanPostProcessor继承自InitDestroyAnnotationBeanPostProcessor;AnnotationAwareAspectJAutoProxyCreator实现spring AOP 动态代理创建的BeanPostProcessor