英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论