Picocli 命令中的注入与 micronaut 之间的互操作性
Interoperability between Injections in Picocli commands and micronaut
在 Micronaut 中定义一个@Singleton bean 不会将相同的实例@Inject 到 Picocli 命令中。
Micronaut 提供与 Picocli 的集成。
看起来,必须做的是,从 Picocli 命令,可以启动 Micronaut 的嵌入式服务器(也许问题已经在这里,Micronaut 的启动只是真正从 Picocli 内部启动?)。
当我通过 @Singleton 将 class 定义为单例,并在 Micronaut 的 Rest-endpoint 和 Picocli 命令中将其 @Inject 时,它注意到这是两个不同的实例并且状态不相同。
我真正想要的是传输通过命令行界面提供的一些状态来配置 backend/Rest-service。
现在我刚刚创建了静态实例来共享这个状态,但我想知道我是否可以让依赖注入在 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 的 运行() 方法中的 SharedState 实例中设置了一些状态,我希望能够从 RestResource 中读取它。因此,我希望在调用其余端点时返回“42”。
有没有什么方法可以以某种方式设置 Micronaut/Picocli,以便 Micronaut/Picocli 的依赖注入容器提前启动并共享?还是 Micronaut 真的只是从 EmbeddedServer 调用开始的?在那种情况下,我必须有哪些选择才能仍然具有一些互操作性?我可以通过某种方式明确向 Micronaut 的 DI 容器请求实例吗?
我认为问题在于问题中的代码创建了两个单独的 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);
}
}
在 Micronaut 中定义一个@Singleton bean 不会将相同的实例@Inject 到 Picocli 命令中。
Micronaut 提供与 Picocli 的集成。 看起来,必须做的是,从 Picocli 命令,可以启动 Micronaut 的嵌入式服务器(也许问题已经在这里,Micronaut 的启动只是真正从 Picocli 内部启动?)。 当我通过 @Singleton 将 class 定义为单例,并在 Micronaut 的 Rest-endpoint 和 Picocli 命令中将其 @Inject 时,它注意到这是两个不同的实例并且状态不相同。 我真正想要的是传输通过命令行界面提供的一些状态来配置 backend/Rest-service。 现在我刚刚创建了静态实例来共享这个状态,但我想知道我是否可以让依赖注入在 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 的 运行() 方法中的 SharedState 实例中设置了一些状态,我希望能够从 RestResource 中读取它。因此,我希望在调用其余端点时返回“42”。
有没有什么方法可以以某种方式设置 Micronaut/Picocli,以便 Micronaut/Picocli 的依赖注入容器提前启动并共享?还是 Micronaut 真的只是从 EmbeddedServer 调用开始的?在那种情况下,我必须有哪些选择才能仍然具有一些互操作性?我可以通过某种方式明确向 Micronaut 的 DI 容器请求实例吗?
我认为问题在于问题中的代码创建了两个单独的 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);
}
}