你如何为构造函数依赖注入编写一个 Akka Typed Extension for Spring?

Jie*_*ong 9 java spring akka akka-typed

在 Akka 2.6 之前,或者使用经典 Actors,可以编写 Akka 扩展以访问 Akka 无类型 actor 中 Spring 的 @Inject 注释。

一个例子是:https : //github.com/typesafehub/activator-akka-java-spring/blob/master/src/main/java/sample/SpringExtension.java

但是,这不适用于新的 Akka Typed 演员。

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

Run Code Online (Sandbox Code Playgroud)

你如何为 Typed Actors 编写 Akka 扩展以允许在类型化 Actor 中使用 Spring DI?

Shi*_*e93 4

可能这并不完全是您所需要的,但我认为找到了一种在不使用扩展的情况下注入类型演员的方法。

我们可以将Behavior创建为bean,注入所有需要的依赖项并将其传递给另一个actor,在该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));
}
Run Code Online (Sandbox Code Playgroud)

然后,在 GreetActor 中,我们只需通过调用从注入的行为创建演员getContext().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;
    }
}
Run Code Online (Sandbox Code Playgroud)

由于我们无法在 Akka Typed 中从 Actor 系统外部创建 Actor,因此我认为没有正确的方法可以使用 Spring 注入 ActorRef。

我们可以尝试将 Spring 上下文注入到 actor 中,生成一些 actor 并将它们放入 Spring 上下文中,但我认为这不是一个同时使用这两个框架的好方法。