资讯动态

《Spring Boot 3:高级与架构设计》第 2 章 IOC 容器的高级机制 BeanDefinitionRegistryPostProcessor 阅读笔记 7

发布时间:2026/9/28 4:35:38 来源:尧图企业网站定制
《Spring Boot 3高级与架构设计》第 2 章 IOC 容器的高级机制 BeanDefinitionRegistryPostProcessor 阅读笔记 72.3.3 BeanDefinitionRegistryPostProcessorBeanDefinitionRegistryPostProcessor 是继承自 BeanFactoryPostProcessor 的另一个后置处理器从接口名也能看出它是针对BeanDefinitionRegistry 的后置处理器。获取 BeanDefinitionRegistry 后可以向其中注册新的 BeanDefinition所以它额外扩展了一个在 BeanFactoryPostProcessor 处理之前触发的回调点这意味着 BeanDefinitionRegistryPostProcessor 可以在 BeanFactoryPostProcessor 之前注册其他的 BeanDefinition。这里请读者着重区分 BeanDefinitionRegistryPostProcessor 与 BeanFactoryPostProcessor后者一般只用来修改、扩展 BeanDefinition 中的信息而前者则可以在 BeanFactoryPostProcessor 处理 BeanDefinition 之前向 BeanDefinitionRegistry 注册新的 BeanDefinition甚至注册新的BeanFactoryPostProcessor 用于下一阶段的回调。BeanDefinitionRegistryPostProcessor 的切入时机是允许新增 BeanDefinition 的环节也就是图中所示的 2 个圆圈变成 3 个圆圈的环节一个圆圈看作一个 BeanDefinition​。这里还有一个细节由于实现 BeanDefinitionRegistryPostProcessor 的类同时也会实现 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法因此容器在执行完所有 BeanDefinitionRegistryPostProcessor 的接口方法后紧接着执行这些类的postProcessBeanFactory 方法最后执行普通的只实现了 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法。2.3.4 BeanDefinitionRegistryPostProcessor 的使用同样地通过实际使用 BeanDefinitionRegistryPostProcessor来体会它如何向 BeanDefinitionRegistry 中注册新的 BeanDefinition。虚拟的需求场景是有一个抽象类 Animal 和两个子类 Cat 和 Dog最初 IOC 容器中只注册一个 Cat 而没有 Dog需要借助BeanDefinitionRegistryPostProcessor 将 Dog 也注册到 IOC 容器中随后利用 BeanFactoryPostProcessor 的扩展点给所有 Animal 类型的 Bean 进行属性赋值。1 声明类首先声明抽象类 Animal 和两个子类 Cat 和 Dog由于该场景中只有动物没有人因此 Person 无须再声明如代码所示。packagecom.yangjunbo.spring.postprocessor.examplei.bean;publicabstractclassAnimal{protectedStringname;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.namename;}}packagecom.yangjunbo.spring.postprocessor.examplei.bean;importorg.springframework.stereotype.Component;ComponentpublicclassCatextendsAnimal{OverridepublicStringtoString(){returnCat{namename\};}}packagecom.yangjunbo.spring.postprocessor.examplei.bean;publicclassDogextendsAnimal{OverridepublicStringtoString(){returnDog{namename\};}}2 编写后置处理器需求描述中强调只有 Cat 率先注册到 IOC 容器中而 Dog 需要借助 BeanDefinitionRegistryPostProcessor 注册所以接下来编写一个注册 Dog 的后置处理器如代码所示。由于 BeanDefinitionRegistryPostProcessor 与 ImportBeanDefinitionRegistrar 注册 BeanDefinition 都是借助BeanDefinitionRegistry 完成的因此注册代码对读者而言并不陌生。packagecom.yangjunbo.spring.postprocessor.examplei.config;importcom.yangjunbo.spring.postprocessor.examplei.bean.Dog;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.BeanDefinition;importorg.springframework.beans.factory.config.ConfigurableListableBeanFactory;importorg.springframework.beans.factory.support.BeanDefinitionBuilder;importorg.springframework.beans.factory.support.BeanDefinitionRegistry;importorg.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;importorg.springframework.core.PriorityOrdered;importorg.springframework.stereotype.Component;ComponentpublicclassDogRegisterPostProcessorimplementsBeanDefinitionRegistryPostProcessor,PriorityOrdered{OverridepublicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistryregistry)throwsBeansException{System.out.println(DogRegisterPostProcessor postProcessBeanDefinitionRegistry run ......);if(!registry.containsBeanDefinition(dog)){BeanDefinitiondogDefinitionBeanDefinitionBuilder.genericBeanDefinition(Dog.class).getBeanDefinition();registry.registerBeanDefinition(dog,dogDefinition);}}OverridepublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{System.out.println(DogRegisterPostProcessor postProcessBeanFactory run ......);}OverridepublicintgetOrder(){return0;}}另外还需要编写一个给 Animal 类型的 Bean 属性赋值的后置处理器如代码所示。packagecom.yangjunbo.spring.postprocessor.examplei.config;importcom.yangjunbo.spring.postprocessor.examplei.bean.Animal;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.BeanDefinition;importorg.springframework.beans.factory.config.BeanFactoryPostProcessor;importorg.springframework.beans.factory.config.ConfigurableListableBeanFactory;importorg.springframework.stereotype.Component;importjava.util.stream.Stream;ComponentpublicclassAnimalNameSetterPostProcessorimplementsBeanFactoryPostProcessor{OverridepublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{System.out.println(AnimalNameSetterPostProcessor postProcessBeanFactory run ......);String[]animalNamesbeanFactory.getBeanNamesForType(Animal.class);Stream.of(animalNames).forEach(name-{BeanDefinitionbeanDefinitionbeanFactory.getBeanDefinition(name);beanDefinition.getPropertyValues().add(name,name);});}}3 测试运行代码编写完毕接下来编写测试类使用组件扫描注解驱动 IOC 容器并从 IOC 容器中取出 Cat 和 Dog如代码所示。运行 main 方法后控制台可以正确打印 Cat 和 Dog 的信息证明 Dog 已被成功注册到 IOC 容器并且后置处理器的属性赋值也完全正确。packagecom.yangjunbo.spring.postprocessor.examplei;importcom.yangjunbo.spring.postprocessor.exampleh.bean.Green;importcom.yangjunbo.spring.postprocessor.exampleh.bean.Red;importcom.yangjunbo.spring.postprocessor.examplei.bean.Cat;importcom.yangjunbo.spring.postprocessor.examplei.bean.Dog;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;/** * ClassName: PostProcessorApplication * Package: com.yangjunbo.spring.postprocessor.examplea * Description: * * Author 杨钧博 * Create 2026/9/8 20:27 * Version 1.0 */publicclassPostProcessorIApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(com.yangjunbo.spring.postprocessor.examplei);Catcatctx.getBean(Cat.class);System.out.println(cat);Dogdogctx.getBean(Dog.class);System.out.println(dog);}}4 运行时机分析上述测试结果已经证明两个后置处理器都成功运行但是 DogRegisterPostProcessor 和 AnimalNameSetterPostProcessor 两个后置处理器的postProcessBeanFactory 方法的执行顺序是什么是有指定的顺序还是 Spring Framework 底层已经确定好了顺序为了弄清这个问题可以在两个后置处理器的所有方法中都额外添加控制台打印如代码所示。重新运行 main 方法控制台打印结果说明BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 执行完毕后再执行它们的 postProcessBeanFactory 方法最后才能轮到普通的 BeanFactoryPostProcessor。2.3.5 后置处理器的对比对比维度处理目标执行时机可操作的空间BeanPostProcessorBeanBean 的初始化阶段前后已创建出 Bean给 Bean 属性赋值、创建代理对象等BeanFactoryPostProcessorBeanDefinitionBeanDefinition 解析完毕并注册进 BeanFactory 之后此时 Bean 未实例化在 BeanDefinition 中增删属性、移除BeanDefinition 等BeanDefinitionRegistryPostProcessorBeanDefinition、.class 文件等配置文件、配置类已解析完毕并注册进 BeanFactory但还没有被 Bean FactoryPostProcessor 处理向 BeanFactory 中注册新的 Bean Definition

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑