Spring中new实例化@Component类时@Inject对象为空问题咨询
问题解答
1. 操作错误原因
你用new A()创建类A的实例是核心错误。类A标注了@Component,属于Spring容器管理的Bean,但Spring仅会为自己创建并管控的Bean实例完成依赖注入。通过new关键字创建的是普通Java对象,不在Spring容器的管理范围内,Spring不会为它注入ServiceClass,所以构造函数里调用该注入类时会出现空指针。
2. 如何在构造函数中调用注入类
推荐使用构造函数注入,这是Spring官方推荐的依赖注入方式,能确保依赖在Bean实例化时就已注入,构造函数中可以直接使用:
@Component public class A { private final ServiceClass serviceClass; // Spring 4.3+ 单构造函数可省略@Autowired/@Inject public A(ServiceClass serviceClass) { this.serviceClass = serviceClass; // 这里可以直接调用serviceClass的方法,不会空指针 serviceClass.someMethod(); } @Scheduled(fixedRate = 300000) // 5分钟 public void scheduledTask() { // 调度方法正常使用serviceClass } }
如果坚持使用字段注入(@Inject),绝对不能在构造函数里调用注入的依赖——因为字段注入是在构造函数执行完成后才进行的。此时需要将构造函数中的逻辑移到@PostConstruct标注的方法中,该方法会在Spring完成所有依赖注入后执行:
@Component public class A { @Inject private ServiceClass serviceClass; public A() { // 这里不能调用serviceClass,此时还未注入 } @PostConstruct public void init() { // 依赖已注入,可安全调用 serviceClass.someMethod(); } @Scheduled(fixedRate = 300000) public void scheduledTask() { // ... } }
3. 是否需要避免使用new?
必须避免。只要是Spring管理的Bean(标注了@Component、@Service等注解的类),都应该通过Spring容器获取实例:
- 在类B中通过
@Inject或@Autowired注入类A的实例,而不是自己new A():
@Component public class B { @Inject private A a; public void doSomething() { a.callsomeutility(); } }
自己new出来的类A实例不仅依赖注入失效,连@Scheduled这类Spring提供的注解功能也不会生效——因为Spring的调度机制只对容器内的Bean生效。
4. 避免使用new后,callsomeutility()会在类加载时执行吗?
不会。类加载阶段只是把类的字节码加载到JVM中,并不会创建对象。Spring单例Bean的执行流程是:
- 容器启动时实例化Bean(创建对象)
- 完成依赖注入
- 执行
@PostConstruct方法(如果有) - Bean进入可用状态
如果callsomeutility()是在构造函数或@PostConstruct方法中调用,它会在Bean实例化并完成依赖注入后执行,而非类加载阶段。
内容的提问来源于stack exchange,提问作者user7965433
相关产品推荐
相关产品推荐

