Picocli 命令中的注入与 micronaut 之间的互操作性 [英] Interoperability between Injections in Picocli commands and micronaut

查看:68
本文介绍了Picocli 命令中的注入与 micronaut 之间的互操作性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Micronaut 中定义 @Singleton bean 不会将相同的实例@Inject 到 Picocli 命令中.

Defining an @Singleton bean in Micronaut does not @Inject the same instance into Picocli commands.

Micronaut 提供与 Picocli 的集成.看起来最重要的是,从 Picocli 命令,可以启动 Micronaut 的 EmbeddedServer(也许问题已经在这里,Micronaut 只是从 Picocli 内部真正启动?).当我通过@Singleton 将一个类定义为单例,并在 Micronaut 的 Rest 端点和 Picocli 命令中@Inject 它时,它注意到这是两个不同的实例并且状态不相同.我主要想要的是传输一些通过命令行界面提供的状态来配置后端/休息服务.现在我刚刚创建了静态实例来共享这个状态,但我想知道我是否可以让依赖注入在 Picocli 和 Micronaut 之间正常工作.

Micronaut offers an integration with Picocli. What is essential done, it seems, is that from the Picocli command, one can start an EmbeddedServer of Micronaut (maybe the problem is already here that Micronaut is started only really started from within Picocli?). When I define a class as singleton via @Singleton, and @Inject it both in a Rest-endpoint of Micronaut and the Picocli command, it notice that these are two different instances and the state is not the same. What I essential want is to transport some state provided via the commandline interface to configure the backend/Rest-service. For now I have just created static instance to share this state but i am wondering if I can get the dependency-injection to work properly between Picocli and 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".

If I set some state in the SharedState instance in the UICommand's run()-method, I expect to be able to read it from the RestResource. So, i would expect to get back "42" when i call the rest endpoint.

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

Is there some way to set up Micronaut/Picocli in some way so the dependency-injection container of Micronaut/Picocli is started early and shared? Or is Micronaut really only started with the EmbeddedServer call? In that case, what options to I have to still have some interoperability? Can i explicitly ask Micronaut's DI container for the instance in some way?

推荐答案

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

I believe that the problem is that the code in the question creates two separate ApplicationContext instances.

在幕后调用 PicocliRunner.run(UICommand.class, args) 创建一个ApplicationContext,而UICommand.run 方法调用 ApplicationContext.run(EmbeddedServer.class),它启动另一个 ApplicationContext 实例.

The call to PicocliRunner.run(UICommand.class, args) under the hood creates an ApplicationContext, while the UICommand.run method calls ApplicationContext.run(EmbeddedServer.class), which starts another ApplicationContext instance.

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

One way to solve this may be to inject the ApplicationContext instead of starting a new one:

@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);
    }
}

这篇关于Picocli 命令中的注入与 micronaut 之间的互操作性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆