对于最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

测试中的 Bean 覆盖

测试中的 Bean 覆盖(Bean overriding)是指通过在测试类上添加注解,或在测试类中一个或多个非静态字段上添加注解,来覆盖 ApplicationContext 中特定的 Bean。spring-doc.cadn.net.cn

此功能旨在作为一种风险较低的替代方案,用于取代通过 @Bean 注册 bean 并将 DefaultListableBeanFactorysetAllowBeanDefinitionOverriding 标志设置为 true 的做法。

Spring TestContext 框架提供了两组用于覆盖 Bean 的注解。spring-doc.cadn.net.cn

前者完全依赖于 Spring,而后者则依赖于 Mockito 第三方库。spring-doc.cadn.net.cn

自定义 Bean 覆盖支持

上述三种注解均基于 @BeanOverride 元注解及其相关基础设施,允许用户定义自定义的 Bean 覆盖变体。spring-doc.cadn.net.cn

要实现自定义的 Bean 覆盖支持,需要以下内容:spring-doc.cadn.net.cn

Spring TestContext 框架包含以下 API 的实现,这些实现支持 Bean 覆盖,并负责设置其余的基础设施。spring-doc.cadn.net.cn

spring-test 模块在其 META-INF/spring.factories 属性文件 中注册了后两种实现(BeanOverrideContextCustomizerFactoryBeanOverrideTestExecutionListener)。spring-doc.cadn.net.cn

bean 覆盖基础设施会搜索测试类上的注解,以及测试类中被 @BeanOverride 元注解标注的非静态字段上的注解,并实例化相应的 BeanOverrideProcessor,该处理器负责创建合适的 BeanOverrideHandlerspring-doc.cadn.net.cn

内部的 BeanOverrideBeanFactoryPostProcessor 随后会使用 Bean 覆盖处理器,根据相应的 ApplicationContext 所定义的方式,通过创建、替换或包装 Bean 来修改测试的 BeanOverrideStrategyspring-doc.cadn.net.cn

REPLACE

替换该 bean。如果对应的 bean 不存在,则抛出异常。spring-doc.cadn.net.cn

REPLACE_OR_CREATE

如果 Bean 已存在,则替换它;如果不存在对应的 Bean,则创建一个新的 Bean。spring-doc.cadn.net.cn

WRAP

获取原始的 Bean 并对其进行包装。spring-doc.cadn.net.cn

只有单例Bean可以被覆盖。任何尝试覆盖非单例Bean的行为都会导致异常。spring-doc.cadn.net.cn

当替换由 FactoryBean 创建的 bean 时,FactoryBean 本身将被替换为一个单例 bean,该单例 bean 对应于由相应的 BeanOverrideHandler 创建的 bean 覆盖实例。spring-doc.cadn.net.cn

当对由FactoryBean创建的 Bean 进行包装时,被包装的是FactoryBean所创建的对象,而不是FactoryBean本身。spring-doc.cadn.net.cn

与 Spring 的自动装配机制(例如解析 @Autowired 字段)不同,TestContext 框架中的 bean 覆盖基础设施在定位要覆盖的 bean 时只能执行有限的启发式策略。要么 BeanOverrideProcessor 能够计算出要覆盖的 bean 的名称,要么可以根据带注解字段的类型及其限定注解明确地选择该 bean。spring-doc.cadn.net.cn

通常,该 bean 由 BeanOverrideFactoryPostProcessor 按类型(by type)进行选择。 或者,用户也可以在自定义注解中直接提供 bean 的名称。spring-doc.cadn.net.cn

BeanOverrideProcessor 的实现也可以根据某种约定或其他方法在内部计算出一个 bean 名称。spring-doc.cadn.net.cn