
在 Spring 6 + JUnit 5 集成测试中,@Autowired 依赖无法注入到 @Scope("prototype") 的嵌套 Bean(如 ExchangeImpl)中,根本原因是 Spring 容器未管理该实例的创建过程;需通过 @Configuration 类定义 @Bean 工厂方法,并确保其被 Spring 上下文加载。
在 spring 6 + junit 5 集成测试中,`@autowired` 依赖无法注入到 `@scope("prototype")` 的嵌套 bean(如 `exchangeimpl`)中,根本原因是 spring 容器未管理该实例的创建过程;需通过 `@configuration` 类定义 `@bean` 工厂方法,并确保其被 spring 上下文加载。
当使用 new ExchangeImpl() 手动构造原型 Bean 时,Spring 容器完全不参与该对象的生命周期管理——即使类上标注了 @Component 和 @Autowired,这些注解也仅对容器托管的 Bean 生效。因此,在 ExchangeCacheImpl.loadAll() 中直接 new ExchangeImpl(),会导致 irregularHoursDAO 和 regularHoursDAO 始终为 null,最终触发 NullPointerException。
✅ 正确做法是:将原型 Bean 的创建委托给 Spring 容器,通过 @Configuration 类提供带 @Bean 和 @Scope("prototype") 的工厂方法:
@Configuration
public class ExchangeConfig {
@Bean
@Scope("prototype")
public Exchange exchangeImpl() {
return new ExchangeImpl();
}
}
⚠️ 关键点:该配置类必须被 Spring 上下文加载。若使用
@ContextConfiguration(locations = {"classpath*:applicationContext.xml"}),需确保 XML 配置中已扫描到该类,或改用基于 Java 的配置(推荐):@ContextConfiguration(classes = {AppConfig.class, ExchangeConfig.class}) @ExtendWith(SpringExtension.class) public class ExchangeDBTest { ... }
随后,在 ExchangeCacheImpl 中注入 ObjectProvider 或直接注入工厂方法(Spring 5.3+ 支持),以按需获取容器托管的实例:
@Service
public class ExchangeCacheImpl implements ExchangeCache {
private final ObjectProvider<exchange> exchangeProvider;
public ExchangeCacheImpl(ObjectProvider<exchange> exchangeProvider) {
this.exchangeProvider = exchangeProvider;
}
private void loadAll() {
Collection<exchangedata> batch = exchangeDAO.findAll();
for (ExchangeData exData : batch) {
if (exData.getMicCode() == null) continue;
Exchange e = exchangeProvider.getObject(); // ✅ 容器创建并完成依赖注入
// ... 初始化逻辑
}
}
}</exchangedata></exchange></exchange>
? 替代方案(更简洁):若 ExchangeImpl 无复杂初始化参数,可直接在配置类中声明其依赖,让 Spring 自动装配:
@Configuration
public class ExchangeConfig {
@Bean
@Scope("prototype")
public Exchange exchangeImpl(
@Qualifier("irregularHoursDAO") ExchangeIrregularHoursDAO irregularDao,
@Qualifier("regularHoursDAO") ExchangeRegularHoursDAO regularDao) {
ExchangeImpl impl = new ExchangeImpl();
impl.setIrregularHoursDAO(irregularDao); // 假设提供 setter
impl.setRegularHoursDAO(regularDao);
return impl;
}
}
? 总结:
-
new Xxx()→ 绕过 Spring 容器 →@Autowired失效; -
@Bean + @Scope("prototype") + @Configuration→ 容器接管创建 → 依赖完整注入; - 确保配置类被
@ContextConfiguration显式包含或自动扫描; - 优先使用
ObjectProvider获取原型 Bean,避免强耦合ApplicationContext。
此方案无需修改 ExchangeImpl 的构造逻辑,符合“最小侵入”原则,且与生产环境行为完全一致。










