使用@Autowired注入无参构造报空指针,单参构造正常问题排查
解决@Autowired注入无参构造函数时的空指针异常问题
我来帮你捋捋这个问题哈!你遇到的情况很典型:给无参构造函数加@Autowired后触发空指针,但单参构造函数却能正常跑,核心原因是构造函数的初始化逻辑+Spring的注入优先级在搞事情,咱们一步步拆解。
先把你给出的代码补全并格式化下,方便分析:
@Component // 标记为Spring管理的Bean public class TennisCoach implements Coach { private FortuneService fortuneservice; // 单参构造函数,初始化了fortuneservice public TennisCoach(FortuneService thefortuneservice) { System.out.println(" inside 1 arg constructter"); fortuneservice = thefortuneservice; } // 加了@Autowired的无参构造函数(你代码没写完,推测是空实现) @Autowired public TennisCoach() { System.out.println(" inside no-arg constructter"); } // 假设你有业务方法用到fortuneservice,比如: @Override public String getDailyFortune() { return fortuneservice.getFortune(); // 这里会触发空指针! } }
问题根源
空指针的直接原因是**fortuneservice没有被初始化**:
- 当Spring用无参构造函数创建
TennisCoach实例时,你没有在构造函数里给fortuneservice赋值,后续调用依赖它的方法自然会抛空指针。 - 而单参构造函数里已经手动把传入的
FortuneService赋值给了成员变量,所以业务方法能正常运行。
另外还有个Spring注入的细节:如果类中有多个构造函数,Spring会优先选择能自动填充所有依赖的构造函数。你的单参构造函数依赖的FortuneService如果是Spring管理的Bean(比如加了@Component),哪怕你给无参构造函数加了@Autowired,Spring大概率还是会优先用单参构造函数——除非你明确指定要使用无参构造。
两种解决思路
思路1:想用无参构造函数,配合字段/Setter注入依赖
如果你的需求是用无参构造创建实例,再注入FortuneService,可以这么改:
@Component public class TennisCoach implements Coach { private FortuneService fortuneservice; // Spring 4.3+版本,无参构造函数可以不用加@Autowired,Spring会自动识别 public TennisCoach() { System.out.println(" inside no-arg constructter"); } // 用Setter注入依赖 @Autowired public void setFortuneservice(FortuneService fortuneservice) { this.fortuneservice = fortuneservice; } // 或者直接用字段注入(更简洁): // @Autowired // private FortuneService fortuneservice; @Override public String getDailyFortune() { return fortuneservice.getFortune(); } }
思路2:保留两个构造函数,明确指定Spring使用的构造
如果你想保留两个构造函数,需要明确告诉Spring优先用哪个,同时确保每个构造函数都能正确初始化依赖:
@Component public class TennisCoach implements Coach { private FortuneService fortuneservice; // 给单参构造加@Autowired,标记为Spring优先使用的构造 @Autowired public TennisCoach(FortuneService thefortuneservice) { System.out.println(" inside 1 arg constructter"); fortuneservice = thefortuneservice; } // 无参构造可以保留,但要么在这里初始化fortuneservice,要么确保Spring不会用它 public TennisCoach() { System.out.println(" inside no-arg constructter"); // 如果需要用这个构造,这里可以手动初始化fortuneservice,比如: // this.fortuneservice = new DefaultFortuneService(); } @Override public String getDailyFortune() { return fortuneservice.getFortune(); } }
额外提醒
- 如果你只有一个构造函数,Spring 4.3+版本不需要加
@Autowired,会自动注入依赖; - 空指针永远是因为某个变量没初始化,排查时先确认变量是否被正确赋值,再看Spring的注入逻辑是否符合预期。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

