有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

当我在构造函数中调用java Autowired属性时,该属性为null

我有一个演示类FooComponent,它在FooService中自动连接并在其构造函数中访问

食物成分。类别:

@Component("fooComponent")
public class FooComponent {
    public String format() {
        return "foo";
    }
}

餐饮服务。类别:

@Component
public class FooService {

    @Autowired
    private FooComponent fooComponent;

    public FooService() {
        System.out.println("in foo service const=" + this.fooComponent);
    }

    String doTatti() {
        return fooComponent.format();
    }
}

主要用途:

@SpringBootApplication
public class InterviewApplication {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(InterviewApplication.class, args);
        System.out.println(ctx.getBean(FooService.class).doTatti());
    }
}

在这个tutorial中,作者说In the above example, Spring looks for and injects fooFormatter when FooService is created.在我的例子中,fooFormatter是fooComponent

但每次,在构造函数中,我的autowired属性都是null。我的假设是,这是因为FoOService尚未完全初始化?这是正确的吗

如果我的假设是正确的,那么为什么下面的代码可以工作呢

@Autowired
public FooService(FooComponent fooComponent) {
        System.out.println("in foo service const=" + fooComponent);
}

我知道这是一个非常基本和愚蠢的问题,但我需要帮助来理解它

更新:

最后一个查询,是否有办法在MainApplication中获取Autowire我的FooService实例,而不是从ApplicationContext获取它

先谢谢你


共 (3) 个答案

  1. # 1 楼答案

    在Spring中,bean在其属性被注入之前被实例化。即:

    1. 首先实例化bean
    2. 注入属性 这是因为spring使用实例化bean的setter方法来注入属性

    这就是您获得NullPointerException的原因

    首选和推荐的选项是使用构造函数注入,而不是属性或setter注入。另外,解决这个问题的方法之一是像您所做的那样创建带有参数的构造函数

    您可以在此处查看完整的说明: https://dzone.com/articles/spring-accessing-injected

    编辑: bean应该由容器管理。如果我们想使用其中一个,我们应该依赖依赖依赖注入,而不是直接调用ApplicationContext。getBean()

    见此帖:Why is Spring's ApplicationContext.getBean considered bad?

  2. # 2 楼答案

    您需要使用构造函数注入而不是setter注入。 setter注入的缺点之一是它不能确保依赖项注入。您不能保证是否注入了某些依赖项,这意味着您可能有一个依赖项不完整的对象。另一方面,构造函数注入不允许在依赖项就绪之前构造对象

  3. # 3 楼答案

    1. 对于你的第一个问题,你是对的。当你需要构造函数中的对象时,你必须使用构造函数注入,而不是@autowired的属性注入
    2. 对于第二个,您可以在main中使用@Autowired prop,但通常在这种情况下,最好在commandLineRunner接口的重写中执行逻辑,如下所示:

      @Autowired
      private FooService foo;
      
      public static void main(String[] args) {
          SpringApplication.run(InterviewApplication.class, args);
      }
      
      @Override
      public void run(String... args) throws Exception {
      foo.doTatti();  
      ...
      }