While injecting the ConfigProperty, getting the null value in constructor, with or without @Inject over the constructor?

huangapple go评论57阅读模式
英文:

While injecting the ConfigProperty, getting the null value in constructor, with or without @Inject over the constructor?

问题

// 以下情况中,在构造函数中访问字段注入时,我观察到一些问题。

// 在下面的情况中,在构造函数中使用或不使用 @Inject 都会得到 null 值。

// `GreetingProvider` 类被标记为 `ApplicationScoped`

@Inject
@ConfigProperty(name = "app.greeting")
private String message;

@Inject // 在构造函数中将字段作为 null 值获取,无论是否使用 @Inject 注解
public GreetingProvider() {
  LOG.debug("Message {}", message);
}

// 可以在 `ApplicationScoped` 的事件监听器中获取值。

// 如果我使用基于构造函数的注入,它可以正常工作。

@Inject
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {
    this.message.set(message);
}

**构造函数应该从字段注入中获取到初始化的值对吗**

期望可以在构造函数中访问使用 `@ConfigProperty` 注入的初始化字段

在使用 `@PostConstruct` 注解的方法或观察 `activated(@Observes @Initialized(ApplicationScoped.class) final Object event)` 事件的方法中可以访问它
英文:

For Helidon MP..

I am observing some problem, in field injection, when accessed in constructor.

In below scenario, getting the null value in constructor, with or without @Inject over the constructor

The GreetingProvider class is annotate with ApplicationScoped

@Inject
@ConfigProperty(name = "app.greeting")
private String message;

@Inject //Getting the field as null with or without @Inject annotation
public GreetingProvider() {   
  LOG.debug("Message {}, message);
}

Can get the value in the event listener for ApplicationScoped.

It works fine if I used constructor based injection.

@Inject
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {   
    this.message.set(message);
}

Shouldn't the constructor get the initialised value from the field injection?

Expecting the initialised field injected with @ConfigProperty to be accessible in constructor.

It is accessible in the method annotated with @PostConstruct or method which observes the event activated(@Observes @Initialized(ApplicationScoped.class) final Object event).

答案1

得分: 2

字段值只能在实例化对象后注入。实例化对象需要调用构造函数。因此,如果你考虑一下,首先调用默认构造函数来构建对象的实例,只有在构造后,字段才按照它们声明的顺序被注入。这就是为什么当你通过默认构造函数访问它们时,所有的 @Inject 字段都将为 null。

处理这种情况的正确方式是通过构造函数注入,就像你的第二个例子中使用 @Inject 标注的构造函数一样。

@Inject
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {   
    this.message.set(message);
}

在这里,你正在确定你的类所需的依赖关系,CDI 管理器将确保将依赖关系传递到用 @Inject 标注的构造函数中。现在,你可以将依赖关系作为构造函数的形式参数访问,并初始化字段。

另一方面,被 @PostConstruct 标注的方法每个实例只会被调用一次,在构造函数、字段和方法注入完成后才会执行。如果你有一些逻辑需要每个实例执行一次,@PostConstruct 是理想的方式。

@PostConstruct
public void executeOncePerInstance(){
   // 在这里你可以安全地访问所有字段和构造函数注入的属性
}

行为类似于构造函数注入,但 CDI 的一些容器实现可能在为 bean 设置 Java 代理的过程中多次调用构造函数。

英文:

Field values can only be injected once the object is instantiated. Instantiating the object requires a call to the constructor. So, if you think about this, your default constructor is invoked to build the instance of the object first and only post-construction are the fields injected in the order they are declared. This is why all the @Inject fields will be null when you access them through the default constructor.

The right way to handle this situation is through constructor injection, using @Inject on the constructor like in your second example.

@Inject
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {   
    this.message.set(message);
}

Here, you are identifying the dependencies required by your class and CDI manager will ensure that the dependencies are passed into the constructor annotated with @Inject. You can now access the dependencies as formal arguments of the constructor and initialize the fields yourself.

The method annotated @PostConstruct OTOH is invoked only once per instance, and after the constructor, field and method injections have finished. If you have some logic to be executed once per instance @PostConstruct is the ideal way.

@PostConstruct
public void executeOncePerInstance(){
   // You can safely access all the field & constructor-injected properties here 
}

The behaviour would be similar to constructor injection, but some container implementations of CDI might invoke the constructor more than once during the process of setting up a Java proxy for the bean.

huangapple
  • 本文由 发表于 2023年4月4日 16:29:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75927147.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定