如何在构造方法中使用Spring注入的依赖?
问题原因
Spring 创建 Bean 的流程是:先调用构造方法实例化对象,之后才会执行字段注入(或 Setter 注入)。所以你在构造方法里调用依赖的方法时,otherComponent1 和 otherComponent2 还没被赋值,自然是 null 状态。另外 @RequestScope 的 Bean 会被 Spring 生成代理,但代理逻辑也是在实例化之后处理的,不影响这个核心问题。
解决方案
有两种常用的解决方式,推荐优先用第一种:
1. 构造方法注入(Spring 官方推荐)
把依赖作为构造方法的参数传入,Spring 会先创建好依赖对象,再传入构造方法,确保构造方法执行时依赖已经可用。Spring 4.3+ 版本中,如果 Bean 只有一个构造方法,甚至可以不用加 @Inject 注解。
@Component @RequestScope public class MyComponent { private final OtherComponent1 otherComponent1; private final OtherComponent2 otherComponent2; public MyComponent(OtherComponent1 otherComponent1, OtherComponent2 otherComponent2) { this.otherComponent1 = otherComponent1; this.otherComponent2 = otherComponent2; // 这里可以安全调用依赖的方法 otherComponent1.someMethod(); otherComponent2.someMethod(); } }
这种方式的好处是:依赖用 final 修饰,保证不可变;Bean 初始化时就确保依赖存在,从根源避免空指针异常;同时更便于单元测试,直接传入模拟的依赖即可。
2. 使用 @PostConstruct 初始化方法
如果一定要保留字段注入,可以用 @PostConstruct 注解标记一个初始化方法,这个方法会在所有依赖注入完成、Bean 初始化完成后执行,此时依赖已经被正确赋值。
@Component @RequestScope public class MyComponent { @Inject OtherComponent1 otherComponent1; @Inject OtherComponent2 otherComponent2; MyComponent() { // 构造方法里依然不能调用依赖方法 } @PostConstruct public void init() { // 这里可以安全调用依赖的方法 otherComponent1.someMethod(); otherComponent2.someMethod(); } }
内容的提问来源于stack exchange,提问作者Chirag Arora
相关产品推荐
相关产品推荐

