
本文介绍如何通过构造器注入替代字段注入,使带运行时参数(如 options)的原型作用域 bean 既能由 spring 容器管理,又能在单元测试中直接实例化并注入 mock 依赖,彻底避免反射、测试专用构造器等反模式。
本文介绍如何通过构造器注入替代字段注入,使带运行时参数(如 options)的原型作用域 bean 既能由 spring 容器管理,又能在单元测试中直接实例化并注入 mock 依赖,彻底避免反射、测试专用构造器等反模式。
在 Spring 应用中,当一个组件(如 Adapter)既需携带运行时传入的数据(例如配置对象 Options),又需依赖外部服务(如 AdapterService)时,常见的误区是采用字段注入(@Autowired + private final 字段),这会导致单元测试难以解耦——因为无法在不启动 Spring 上下文的前提下注入 Mock。
✅ 正确做法是:统一使用构造器注入,并将所有依赖(包括服务和参数)声明为构造函数参数。Spring 对原型(@Scope("prototype"))Bean 同样支持全构造器注入,且能自动解析单例 Bean(如 AdapterService)与运行时参数的组合。
以下是重构后的规范写法:
@Service
@Scope("prototype")
final class Adapter {
private final AdapterService adapterService;
private final Options options; // 建议命名语义清晰,避免 s 等模糊缩写
// @Autowired 可省略(Spring 5.0+ 单构造器场景自动识别)
Adapter(AdapterService adapterService, @NotNull Options options) {
this.adapterService = adapterService;
this.options = options;
}
// 示例业务方法,体现依赖使用
public Result process() {
return adapterService.callExternalApi(options);
}
}在 Spring 环境中使用时,可通过 ApplicationContext 动态获取实例:
// 运行时:由 Spring 注入 AdapterService,传入 Options
Options runtimeOptions = new Options("prod", 30_000);
Adapter adapter = applicationContext.getBean(Adapter.class, runtimeOptions);而在纯单元测试中(无 Spring Context),可完全脱离容器,自由注入 Mock:
class AdapterTest {
@Test
void process_callsServiceWithCorrectOptions() {
// Given
AdapterService mockService = Mockito.mock(AdapterService.class);
Options testOptions = new Options("test", 5_000);
Adapter underTest = new Adapter(mockService, testOptions);
Result expected = new Result("success");
Mockito.when(mockService.callExternalApi(testOptions)).thenReturn(expected);
// When
Result actual = underTest.process();
// Then
assertThat(actual).isEqualTo(expected);
Mockito.verify(mockService).callExternalApi(testOptions);
}
}⚠️ 注意事项:
- 避免混合注入方式(如构造器 + 字段注入),会降低可测性与可维护性;
- @Scope("prototype") 不影响构造器注入能力,Spring 仍能解析其依赖图;
- 若 Options 本身也是 Spring Bean,需确保其作用域兼容(如 @Scope("prototype") 或 @Scope("singleton"));
- 使用 Lombok 的 @RequiredArgsConstructor 可进一步简化代码,但需显式标注 @NonNull 以保障空安全。
这种设计兼顾了生产环境的容器集成性与测试场景的轻量可控性,是 Spring 官方推荐的现代依赖注入实践。

















