Spring测试配置中@Value注入Resource为空问题求助
问题原因分析
这个问题的核心是Spring Bean初始化过程中注入顺序的优先级,以及父类与子类注入点的处理顺序导致的。我们一步步拆解你的场景:
1. Spring处理@Configuration类的初始化流程
当Spring创建TestConfiguration这个Bean时,流程是这样的:
- 先实例化
TestConfiguration对象(调用无参构造器) - 接着处理依赖注入:Spring会优先处理父类
BaseConfiguration中的注入点,再处理子类TestConfiguration的注入点
2. 父类@Autowired字段导致的提前调用
你的BaseConfiguration中有@Autowired @Qualifier("foo") protected Object foo字段,当Spring处理这个父类的注入点时:
- 需要去容器中获取
foo这个Bean,而它是由TestConfiguration的foo()@Bean方法创建的 - 此时Spring会直接调用
foo()方法,但注意:子类的@Value("classpath:derby-db.sql") private Resource dbScript还没被注入——因为父类注入点的处理优先级高于子类,子类的字段注入还没轮到 - 所以此时
foo()方法中打印的dbScript自然是null
3. 移到子类后正常的原因
当你把@Autowired的foo字段移到TestConfiguration中后:
- Spring处理注入点时,会先处理子类的所有注入点,
@Value修饰的dbScript会在处理@Autowired foo之前完成赋值 - 当Spring调用
foo()方法创建Bean时,dbScript已经被正确初始化,所以能正常打印
额外补充:@Configuration类的代理特性
还要注意,@Configuration类会被Spring用CGLIB代理,目的是保证@Bean方法调用返回的是容器中的单例Bean。但在这个场景中,代理机制并没有改变注入顺序的问题,核心还是父类与子类注入点的处理优先级。
替代解决办法
如果你不想把字段移到子类,也可以调整逻辑,把依赖dbScript的操作延迟到所有注入完成后执行,比如用@PostConstruct注解:
@Slf4j @Configuration public class TestConfiguration extends BaseConfiguration { @Value("classpath:derby-db.sql") private Resource dbScript; private Object foo; @Bean public Object foo() { foo = new Object(); return foo; } @PostConstruct public void init() { // 这里所有依赖注入已完成,dbScript有值 log.info("{}", dbScript); } @Override protected Object getFoo() { return foo; } }
内容的提问来源于stack exchange,提问作者miro
相关产品推荐
相关产品推荐

