Как написать расширение Akka Typed для Spring для внедрения зависимостей конструктора?

До версии Akka 2.6 или с классическими акторами можно написать расширение Akka, чтобы иметь доступ к аннотации Spring @Inject в нетипизированных акторах Akka.

Один из примеров: 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/exnding.html#building-an-extension).

Пока что я написал это начало расширения, но я не знаю, как связать Spring ApplicationContext с системой акторов:

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

Как написать расширение Akka для типизированных актеров, позволяющее использовать Spring DI в типизированных актерах?


person Jiehong    schedule 30.01.2020    source источник
comment
Вы нашли какую-нибудь информацию по этому поводу? Я тоже ищу это   -  person Jonck van der Kogel    schedule 30.04.2020
comment
Я еще не нашел никакой информации   -  person Jiehong    schedule 07.05.2020


Ответы (1)


Возможно, это не совсем то, что вам нужно, но я думаю, что нашел способ, как вводить типизированных актеров без использования расширения.

Мы можем создать Behavior как bean-компонент, внедрить все необходимые зависимости и передать их другому актору, где он будет порожден на основе определенного Behavior.

Предположим, у нас есть PrintActor, который может печатать сообщения с помощью PrintService, и GreetActor, который использует GreetService и порождает PrintActor. Мы можем определить beans так:

@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 мы просто создаем актера из внедренного поведения, вызывая 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;
    }
}

Поскольку мы не можем создавать акторов вне системы акторов в Akka Typed, я думаю, что нет правильного способа внедрить ActorRef с помощью Spring.

Мы можем попытаться внедрить контекст Spring в актор, создать некоторых актеров и поместить их в контекст Spring, но я думаю, что это не лучший способ работать с обоими фреймворками.

person Shide93    schedule 15.05.2020