java - 你如何为构造函数依赖注入编写一个 Akka Typed Extension for Spring?
问题描述
在 Akka 2.6 之前,或者使用经典的 Actors,可以编写一个 Akka Extension 来访问 Akka 无类型 Actors 中的 Spring 的 @Inject 注释。
但是,这不适用于新的 Akka Typed actor。
Akka 的文档没有显示如何进行这样的扩展(但它确实显示了如何进行简单的扩展:https ://doc.akka.io/docs/akka/current/typed/extending.html#building-an-extension ) .
到目前为止,我写了这个扩展的开头,但是我不知道如何将Spring的ApplicationContext与actor系统联系起来:
import org.springframework.context.ApplicationContext;
import akka.actor.typed.ActorSystem;
import akka.actor.typed.Extension;
import akka.actor.typed.ExtensionId;
public class SpringExtension implements Extension {
private volatile ApplicationContext applicationContext;
private SpringExtension(final ActorSystem<?> system) {
// TODO: What do you put here?
}
void initialize(final ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public static class Id extends ExtensionId<SpringExtension> {
private static final Id instance = new Id();
private Id() {}
// called once per ActorSystem
@Override
public SpringExtension createExtension(final ActorSystem<?> system) {
return new SpringExtension(system);
}
public static SpringExtension get(final ActorSystem<?> system) {
return instance.apply(system);
}
}
}
你如何为类型化 Actor 编写一个 Akka 扩展,允许在类型化 Actor 中使用 Spring DI?
解决方案
可能这不是您所需要的,但我认为找到了一种无需使用扩展即可注入类型化演员的方法。
我们可以将 Behavior 创建为 bean,注入所有需要的依赖项并将其传递给另一个 Actor,在那里根据定义的 Behavior 生成 Actor。
假设我们有可以使用 PrintService 打印消息的 PrintActor,以及使用 GreetService 并生成 PrintActor 的 GreetActor。我们可以这样定义bean:
@Bean
public Behavior<String> printActorBehavior(PrintService printService) {
return Behaviors.setup(ctx -> new PrintActor(ctx, printService));
}
@Bean
public Behavior<GreetActor.Greet> greetActorBehavior(GreetService greetService,
Behavior<String> printerActorBehavior) {
return Behaviors.setup(ctx -> new GreetActor(ctx, greetService, printerActorBehavior));
}
然后,在 GreetActor 中,我们只需通过调用从注入的 Behavior 创建actorgetContext().spawn(printerActorBehavior, "printer");
public class GreetActor extends AbstractBehavior<GreetActor.Greet> {
private GreetService greetService;
private Behavior<String> printerActorBehavior;
public GreetActor(ActorContext<Greet> context,
GreetService greetService,
Behavior<String> printerActorBehavior) {
super(context);
this.greetService = greetService;
this.printerActorBehavior = printerActorBehavior;
}
@Override
public Receive<Greet> createReceive() {
return newReceiveBuilder()
.onMessage(Greet.class, this::onGreet)
.build();
}
private Behavior<Greet> onGreet(Greet msg) {
ActorRef<String> printer = getContext().spawn(printerActorBehavior, "printer");
printer.tell(greetService.greet(msg.name));
return this;
}
@Value
static class Greet {
String name;
}
}
由于我们无法在 Akka Typed 中从演员系统之外创建演员,我认为没有合适的方法来使用 Spring 注入 ActorRef。
我们可以尝试将 Spring 上下文注入到 Actor 中,生成一些 Actor 并将它们放入 Spring 上下文中,但我认为这不是使用这两个框架的好方法。
推荐阅读
- sql-server - SQL- 将 Sum int 转换为 Decimal
- kubernetes - 防止两个作业在 Kubernetes 中并行运行
- google-search - 向谷歌搜索结果添加子链接
- javascript - Publicly View Models in Fusion360 Folder
- angular - 如何在 Angular 4 应用程序中实现站点搜索 Google Analytics
- c# - 从 OuterHtml 获取 TextContent
- c++ - 为什么我在尝试打印单链表中的元素时得到这个永无止境的循环
- reactjs - 在 React 中嵌入 Power Bi 中捕获书签
- typescript - 如何在打字稿中定义连接函数
- elasticsearch - 弹性搜索排序 - 非嵌套元素