在JakartaEE / Helidon / Microprofile中手动实例化的类中使用ConfigProperty

问题描述

我在Helidon start中有一个小应用程序。它主要是一个REST接口,但我也想启动一些后台监视/登录启动。

我希望该监视可以通过config激活/停用。 我面临的问题是,如果手动实例化我的类,则配置不会被提取

这是一个非常简短的代码段:

启动应用程序

public class Main {

    private Main() { }

    public static void main(final String[] args) throws IOException {
        Server server = startServer();

        CellarMonitoring monitoring = new CellarMonitoring();
        monitoring.start();
    }

    static Server startServer() {
        return Server.create().start();
    }
}

是否根据配置开始监视:

package nl.lengrand.cellar;

import org.eclipse.microprofile.config.inject.ConfigProperty;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

public class CellarMonitoring {

    @Inject
    @ConfigProperty(name = "monitoring.enabled",defaultValue = "true")
    private volatile boolean monitoringEnabled; <= Always false

    public void start(){
        if(monitoringEnabled) {
            System.out.println("Monitoring enabled by config. Starting up");
        }
        else System.out.println("Monitoring disabled by config");
    }
}

无论执行什么操作,此代码都将始终返回“配置禁用监视”。

由于onStartup方法永远不会被触发,因此直接访问like described in the documentation也不是一种选择。

在我的服务器中注入一个类以使其可以根据需要访问配置的正确方法是什么?

解决方法

您的问题实际上是关于CDI的。

为了使任何类型的依赖项注入都能与CDI一起使用,CDI必须实例化要注入的事物。在这种情况下, you 实例化要注入的对象,因此CDI永远不会“看到”它,因此也永远不会注入它。

我在这里推测,但是我猜您的用例实际上只是:“我希望CellarMonitoring组件在CDI出现时得到通知。我该怎么做?”

此问题在本网站和其他地方都有很多答案。本质上,您利用了CDI将触发一个事件的事实,该事件在应用程序范围的初始化中通知所有感兴趣的侦听器。应用程序范围实际上是应用程序本身的寿命,因此您可以将其视为启动事件。

full CDI tutorial超出了本问答的范围,但是,为了追赶,这是一种实现方法。我不得不做出各种假设,例如您希望CellarMonitoring像单身人士一样:

@ApplicationScoped
public class CellarMonitoring {

  @Inject
  @ConfigProperty(name = "monitoring.enabled",defaultValue = "true")
  private volatile boolean monitoringEnabled; // <= Always false

  public void start() {
    if (monitoringEnabled) {
      System.out.println("Monitoring enabled by config. Starting up");
    } else {
      System.out.println("Monitoring disabled by config");
    }
  }

  private void onStartup(@Observes @Initialized(ApplicationScoped.class) final Object event) {
    // The container has started.  You can now do what you want to do.
    this.start();
  }

}