我已经通过play-akka配置文件为数据库操作分配了一个专用线程池。现在我正在使用actor系统注入需要此线程池的服务并访问执行上下文。
public class ServiceA{
final Executor executionContext;
@Inject
public ServiceA(ActorSystem system) {
this.executionContext = system.dispatchers().lookup("akka.actor.db-context");
}
但这使得测试ServiceS变得困难。我想做的只是直接注入Executor,如下所示:
public class ServiceA{
final Executor executionContext;
@Inject
public ServiceA(Executor dbExecutionCtx) {
this.executionContext = dbExecutionCtx;
}
我该如何实现这一目标?我已经尝试创建一个guice模块来注入Executor但它错误地抱怨没有启动的应用程序,并且当它执行它绑定类时无法访问ActorSystem。
我使用一种模式,我可以在任何我想要的地方获得EC。我在Singleton中创建了一个ActorSystem
并将其注入我的服务中。
我有一个使用ActorSystems,Dispatchers的设计以及更多用于监控的设计。看看这个,看看你是否可以整合它。
因此,如果将MyActorSystem注入到您的班级,您可以从中访问EC。看看MyDispatcher
和EC的使用:
@Singleton
public class MyActorSystem implements IMyActorSystem{
ActorSystem system;
public MyActorSystem() {
system = ActorSystem.create();
}
public ActorRef create() {
final ActorRef actor = system.actorOf(
Props.create(MyWorker.class).withDispatcher("my-disp")
);
return actor;
}
public void shutdown(){
system.shutdown();
}
public ExecutionContextExecutor getDispatcher(){
return system.dispatcher();
}
}
public class MyDispatcher implements IMyDispatcher {
MyActorSystem system;
@Inject public MyDispatcher(MyActorSystem system) {
this.system = system;
}
public CompletableFuture<Object> dispatch(final Object story) {
List<CompletableFuture<Object>> futureList = new ArrayList<>();
final ActorRef actor = system.create();
final CompletableFuture<Object> completed = FutureConverter
.fromScalaFuture(Patterns.ask(actor, story, 50000)).executeOn(system.getDispatcher())
.thenApply(i -> (Object) i);
return completed;
}
public ExecutionContextExecutor getDispatcher(){
return system.getDispatcher();
}
}
从2.6开始播放其默认调度程序的DI绑定,如下所示:
bind[ExecutionContextExecutor].toProvider[ExecutionContextProvider],
bind[ExecutionContext].to[ExecutionContextExecutor],
bind[Executor].to[ExecutionContextExecutor],
ExecutionContextProvider
在哪里
@Singleton
class ExecutionContextProvider @Inject() (actorSystem: ActorSystem) extends Provider[ExecutionContextExecutor] {
def get = actorSystem.dispatcher
}
看起来Play不会在DI绑定中暴露其他命名的调度程序,因此您可以使用@Named
绑定以相同的方式自行完成。还可以编写Play DI模块,该模块将动态地将所有命名的akka调度程序公开为对应的命名绑定。