Picocli命令中的注射与Micronaut之间的互操作性

时间:2019-06-24 06:32:33

标签: micronaut picocli

在Micronaut中定义@Singleton bean不会将同一实例注入Picocli命令中。

Micronaut提供了与Picocli的集成。 从Picocli命令看来,完成的基本工作是可以启动Micronaut的EmbeddedServer(也许已经存在的问题是Micronaut仅在Picocli内部真正启动了?)。 当我通过@Singleton将一个类定义为singleton并在Micronaut的Rest-endpoint和Picocli命令中将它们都@Inject时,它会注意到这是两个不同的实例,并且状态不相同。 我本质上想要的是传输通过命令行界面提供的某些状态以配置后端/ Rest服务。 现在,我刚刚创建了静态实例来共享此状态,但是我想知道是否可以使依赖注入在Picocli和Micronaut之间正常工作。

@Singleton
public class SharedState {
    private int num;

    public void setNum(int num) { this.num = num };
    public int getNum() { return this.num; };
}

@Command(name = "ui", description = "...", mixinStandardHelpOptions = true)
public class UICommand implements Runnable {

    @Inject
    SharedState state;

    public static void main(String[] args) throws Exception {
        PicocliRunner.run(UICommand.class, args);
    }

    public void run() {
        EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class);
        state.setNum(42);
    }
}

@Controller("/rest")
public class RestResource{

    @Inject
    SharedState state;

    @Get
    public String get() {
        return state.getNum();
    }
}

如果我在UICommand的run()方法的SharedState实例中设置了一些状态,则希望能够从RestResource读取它。因此,当我调用其余端点时,我希望返回“ 42”。

是否可以通过某种方式设置Micronaut / Picocli,以便Micronaut / Picocli的依赖项注入容器能早启动并共享?还是Micronaut真的仅从EmbeddedServer调用开始?在那种情况下,我必须选择哪些选项才能保持互操作性?我可以通过某种方式明确向Micronaut的DI容器询问实例吗?

1 个答案:

答案 0 :(得分:1)

我认为问题在于问题中的代码创建了两个单独的ApplicationContext实例。

creates an ApplicationContext下调用PicocliRunner.run(UICommand.class, args),而UICommand.run方法调用ApplicationContext.run(EmbeddedServer.class),这将启动另一个ApplicationContext实例。

解决此问题的一种方法可能是注入ApplicationContext而不是开始一个新的:

@Command(name = "ui", description = "...", mixinStandardHelpOptions = true)
public class UICommand implements Runnable {

    @Inject
    SharedState state;

    @Inject
    ApplicationContext appContext;

    public static void main(String[] args) throws Exception {
        PicocliRunner.run(UICommand.class, args);
    }

    public void run() {
        // start the injected, shared, application context (not a new instance)
        if (!appContext.isRunning()) { // future versions of PicocliRunner may start the context
            appContext.start();
        }

        // start the embedded server
        EmbeddedServer server = appContext.getBean(EmbeddedServer.class);
        if (!server.isRunning()) {
            server.start();
        }
        state.setNum(42);
    }
}