- invokeBeanFactoryPostProcessors作用
- 源码分析
- 扩展点分析
- 源码分析一ConfigurationClassPostProcessor注入时机
- demo实验
- 总结:
源码分析按照顺序实例化并调用所有已注册的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor
AnnotationConfigServletWebServerApplicationContext调用时完成xml,注解,@import等解析,生成BeanDefinition并注册到beanfactory容器
- 通过委托模式调用BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessors 注意此时从ApplicationContext中获取相关(get)BeanFactoryPostProcessors
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()));
}
}
核心流程如下
-
从ApplicationContext获取的beanFactoryPostProcessors[如下代码中的三个]
-
1 先对外部传入的进行调用postProcessBeanDefinitionRegistry
-
2 其次获取当前bean容器的BDmap,找出实现了PriorityOrdered的BDRPP (实际也就是ConfigurationClassPostProcessor)
-
调用ConfigurationClassPostProcessor完成对所有注解,xml,@import @Bean等全部DB的解析加载
-
3 对上一步生成的BD,继续找容器中存在实现Ordered的BDRPP 进行调用
-
4 继续找容器中没有实现优先级的的BDRPP 进行调用
-
5 然后调用BDRPP和外部容器传入的BFPP的postProcessBeanFactory
-
6 获取容器的BFPP,按照PriorityOrdered,Ordered和普通的分类排序
-
7 调用PriorityOrdered的postProcessBeanFactory
-
8 调用Ordered的postProcessBeanFactory
-
9 调用普通的BFPP的postProcessBeanFactory
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List扩展点分析beanFactoryPostProcessors) { Set processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List regularPostProcessors = new ArrayList<>(); List registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; - 1 先对外部传入的进行调用postProcessBeanDefinitionRegistry registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } List currentRegistryProcessors = new ArrayList<>(); - 2 其次获取当前bean容器的BDmap,找出实现了PriorityOrdered的BDRPP 实际也就是ConfigurationClassPostProcessor - 调用**ConfigurationClassPostProcessor**完成对所有注解,xml,@import @Bean等全部DB的解析加载 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); - 3 对上一步生成的BD,继续找容器中存在实现Ordered的BDRPP 进行调用 - 这里一般是外部框架切入点 比如dubbo的OverrideBeanDefinitionRegistryPostProcessor和DubboConfigBeanDefinitionConflictProcessor postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); - 4 继续找容器中没有实现优先级的的BDRPP 进行调用 递归找,直到容器中的都被处理过 - 要防止调用过程中生成新的BDRPP boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } - 5 然后调用BDRPP和外部容器传入的BFPP的postProcessBeanFactory invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } - 6 获取容器的BFPP,按照PriorityOrdered,Ordered和普通的分类排序 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List priorityOrderedPostProcessors = new ArrayList<>(); List orderedPostProcessorNames = new ArrayList<>(); List nonOrderedPostProcessorNames = new ArrayList<>(); 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); } } - 7 调用PriorityOrdered的postProcessBeanFactory sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); - 8 调用Ordered的postProcessBeanFactory List orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); - 9 调用普通的BFPP的postProcessBeanFactory List nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); beanFactory.clearmetadataCache(); }
| 外部传入bdrpp | 作用 |
|---|---|
| ConfigurationWarningsPostProcessor | 日志警告 如果存在不合理的scanpackage 比如包路径为null,或者org.springframework以及org命令的扫描包 则输出警告信息 |
| configPropertySourcesProcessor | 主要为了处理属性值顺序问题 |
| CachingmetadataReaderFactoryPostProcessor | 为ConfigurationClassPostProcessor设置metadataReaderFactory属性 |
- 上文介绍里外部Applicationcontext并没有传入改BDRPP,那么beanfactory自身的BeanDefinitionMap是怎么持有其对应的BeanDefinition
- AnnotationConfigUtils.registerAnnotationConfigProcessors会判断beanfactory存不存在该BDRPP,不存在则构建RootBeanDefinition 注册到beanfactory
- 该工具还完成另外两个重要的BeanPostProcessors的注册AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor(后面会介绍)
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionevaluator = new Conditionevaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
demo实验
- 问题: 为什么不按PriorityOrdered顺序执行 而是在Ordered的顺序处执行
- 答案:因为PriorityOrdered本身是Ordered的子实现
- 答案: 此外在ConfigurationClassPostProcessor没有执行前,beanfactory中并没有解析 BeanDefinitionRegistryPostProcessorImpl 生成相关BeanDefinition,也就是说在PriorityOrdered处执行相关BDRPP方法时时无法获取改BDRPP信息
@Component
public class BeanDefinitionRegistryPostProcessorImpl implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("不按PriorityOrdered执行顺序执行");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public int getOrder() {
return 0;
}
}
总结:
- 调用invokeBeanFactoryPostProcessors的核心是调用ConfigurationClassPostProcessor完成BeanDefinition的注册
- 自定义的BeanDefinitionRegistryPostProcessor是核心的扩展点,像dubbo,apollo mybatis等诸多框架都借助其完成与spring整合
- 一般自定义BDRPP有顺序要求实现Ordered接口,假设想在PriorityOrdered处执行BDRPP的扩展点方法,则需要在invokeBeanFactoryPostProcessors之前手动将预执行的BDRPP对应的BeanDefinition,注册到beanfactory的BeanDefinitionMap中



