概述
在spring-ioc核心方法中,创建BeanFactory以及解析xml配置文件的方法之后,接下来还有一个重要的方法 invokeBeanFactoryPostProcessors(beanFactory);
这个方法 会 取出 IOC容器里 所有实现了BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口的BeanNames, 然后实例化,分别调用
- 实现自BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法。
- 实现自BeanFactoryPostProcessor postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法。
注意,同BeanPostProcessor接口实例不同, 这两个接口的实例,只会在 所有常规Bean,生成BeanDefinition之后,Bean真正实例化之前被调用一次。而BeanPostProcessor接口实例 在每一个Bean的实例化过程中 都会被依次调用。
BeanFactoryPostProcessor接口
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
方法入参 可以拿到beanFactory实例, 利用该对象提供的api可以对容器里的bean进行一些操作。
BeanDefinitionRegistryPostProcessor接口
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
BeanDefinitionRegistryPostProcessor 接口实现了BeanFactoryPostProcessor, 那么实现BeanDefinitionRegistryPostProcessor 就可以实现两个接口对应的方法,同时拿到
BeanFactory和BeanDefinitionRegistry实例。
应用
自己声明一个类,实现BeanDefinitionRegistryPostProcessor接口, 就会在该阶段被调用对应方法,拿到入参BeanDefinitionRegistry,BeanFactory实例,在Bean实例化之前 对容器里的BeanDefinition做增删改查,操作Bean等等。
@Component
public class Bfp implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 注册BeanDefinition
registry.registerBeanDefinition();
// 删除
registry.removeBeanDefinition();
// 拿到所有beanDefinitionName
for (String beanDefinitionName : registry.getBeanDefinitionNames()) {
BeanDefinition beanDefinition = registry.getBeanDefinition(beanDefinitionName);
// 修改beanDefinition
beanDefinition.setDependsOn();
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 提前实例化bean
beanFactory.getBean("beanName");
// 注册自定义bean作用域
beanFactory.registerScope("aa", new Scope() {
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
}
@Override
public Object remove(String name) {
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
});
}
}
调用流程解析
1.BeanDefinitionRegistryPostProcessor接口的调用
点进该方法
getBeanFactoryPostProcessors() 会从上下文内部的beanFactoryPostProcessors容器里拿,这个时候是空的。
1.1. 先调用已有的getBeanFactoryPostProcessors()已有的实例
由于容器刚开始没有值,这个时候可以跳过。
2.再调用实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor类型实例的方法
先取出BeanDefinitionRegistryPostProcessor类型的BeanName集合,判断是不是实现了PriorityOrdered接口,是的话先实例化, 然后按照PriorityOrdered接口排序,
最终调用postProcessBeanDefinitionRegistry方法。
3. 再调用实现Ordered接口的BeanDefinitionRegistryPostProcessor类型实例的方法
和上面的流程一样,没被处理过的,先实例化,然后按照Ordered接口排序,然后调用它的postProcessBeanDefinitionRegistry方法。
4.再调用没实现以上两种排序接口的实例
[图片上传失败...(image-e19b4d-1642232833930)]
5.最后按照排序优先级,调用实现自BeanFactoryPostProcessor接口的postProcessBeanFactory方法
2.BeanFactoryPostProcessor接口实例的调用
对只实现了BeanFactoryPostProcessor接口的实例进行调用,流程和调用BeanDefinitionRegistryPostProcessor实例 一样:
- 取出BeanFactoryPostProcessord的BeanNames
- 按排序接口优先级,先实例化
- 再调用BeanFactoryPostProcessor接口的postProcessBeanFactory方法。
总结:
1.BeanDefinitionRegistryPostProcessor类的调用
- 首先从BeanDifinition中获取到所有BeanDefinitionRegistryPostProcessor类的bean
- 判断时候实现PriorityOrdered,有的话,实例化,加入的容器中
- 对容器中的bean进行排序,然后调用bean的postProcessBeanDefinitionRegistry
- 清空容器
- 判断时候实现Order接口,有的话,实例化,加入的容器中
- 对容器中的bean进行排序,然后调用bean的postProcessBeanDefinitionRegistry方法
- 清空容器
- 接下来是对没有实现排序接口的BeanDefinitionRegistryPostProcessor进行实例化
- 循环bean,然后调用bean的postProcessBeanDefinitionRegistry方法
2.BeanFactoryPostProcessor类的调用
同 BeanDefinitionRegistryPostProcessor类的调用逻辑是一样的,都是排序,实例化,调用postProcessBeanFactory方法
注意点:
实现这两个接口的类会在这里就已经触发getBean的操作,就是实例化,实现的方法会传入beanDefinitionRegistry和beanFactory对象
beanDefinitionRegistry可以在实现的方法里面对beanDefinition进行修改和新增,可以在这里自己创建beanDefinition加入到它里面的容器中,后续会实例化
beanFactory ,可以直接对bean进行操作