访问模块中的Play 2 ActorSystem引用

时间:2017-11-29 15:22:29

标签: java dependency-injection playframework akka guice

根据游戏2.6的documentation

  

已弃用的静态方法play.libs.Akka.system和play.api.libs.concurrent.Akka.system已被删除。使用依赖注入来获取ActorSystem的实例并访问actor系统。

doc提供了一个使用POJO注释的示例,但是在模块中使用时语法似乎不起作用...

我们的类def看起来像这样:

public class SomeMagicalModule extends AbstractModule implements AkkaGuiceSupport {...}

1)尝试在类成员上使用@Inject会产生NULL引用:

    @Inject
    protected ActorSystem system;

2)尝试在模块的构造函数上使用@Inject会抛出 play.api.PlayException:没有有效的构造函数

    public SomeMagicalModule (@Inject AkkaSystem system) {...}

是否有其他途径可以获得AkkaSystem,还是我们错过了一些简单的东西?

TIA。

2 个答案:

答案 0 :(得分:2)

您可以使用@ Provides

  

当您需要代码来创建对象时,请使用@Provides方法。该方法必须在模块中定义,并且必须具有@Provides注释。方法的返回类型是绑定类型。 只要注入器需要该类型的实例,它就会调用该方法。   如果@Provides方法具有@PayPal或@Named(“Checkout”)等绑定注释,则Guice会绑定注释类型。 依赖关系可以作为参数传递给方法。在调用方法之前,进样器将为每个进行绑定。

@Provides
CreditCardProcessor providePayPalCreditCardProcessor(@Named("PayPal API key") String apiKey) {
  PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();
  processor.setApiKey(apiKey);
  return processor;
}

但是,你应该考虑到

  

只要注入器需要该类型的实例,它就会调用方法

因此,如果你有两个依赖于提供的组件的组件,在这种情况下是CreditCardProcessor,那么你最终会得到这个组件的2个实例,因为Guice注入器会调用每次需要注入此类型的实例时该方法。

Scopes为此提供解决方案,您必须添加@Singleton注释。

@Provides
@Singleton
CreditCardProcessor providePayPalCreditCardProcessor(@Named("PayPal API key") String apiKey) {
  PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();
  processor.setApiKey(apiKey);
  return processor;
}

在你的情况下,它将是

public class SomeMagicalModule extends AbstractModule implements AkkaGuiceSupport {

  @Provides
  @Singleton
  @Named("some-actor")
  ActorRef createActor(system: ActorSystem){
    system.actorOf(...)
  }
}

致codejanovic的信用,请参阅his answer

无论如何,如果你想引用ActorSystem来创建Actors,你应该使用AkkaGuiceSupport(我看到你已经将它添加到你的模块中,但你似乎没有使用它)。

答案 1 :(得分:0)

模块实际上不能有@Inject注释。您可以使用模块来配置注入的工作方式,但不能将注入事项注入其中。原因是Play / Guice首先创建并配置所有模块,然后进行注入。在配置完成之前,无法进行注射。

关于模块的Guice文档:https://github.com/google/guice/wiki/Bindings#creating-bindings

您可以在Guice创建的其中一个对象中获得ActorSystem,例如控制器:

public class MyController {
  @Inject // <--- goes before constructor not on parameter
  public MyController(ActorSystem actorSystem) { ... }
  ...
}

关于@Inject的Guice文档:https://github.com/google/guice/wiki/Injections#injections