如何将自定义 Executor 注入到 play 应用程序中?

Posted

技术标签:

【中文标题】如何将自定义 Executor 注入到 play 应用程序中?【英文标题】:How do I inject a custom Executor into a play application? 【发布时间】:2016-06-14 01:20:56 【问题描述】:

我已经通过 play-akka 配置文件为数据库操作分配了一个专用线程池。现在,我正在向参与者系统注入需要此线程池的服务并访问执行上下文。

 public class ServiceA

     final Executor executionContext;

     @Inject
     public ServiceA(ActorSystem system) 
        this.executionContext = system.dispatchers().lookup("akka.actor.db-context");
 

但这使得测试 ServiceA 变得很困难。我想做的只是像这样直接注入 Executor:

 public class ServiceA

     final Executor executionContext;

     @Inject
     public ServiceA(Executor dbExecutionCtx) 
        this.executionContext = dbExecutionCtx;
 

我如何实现这一目标?我尝试创建一个 guice 模块来注入 Executor,但它错误地抱怨没有启动的应用程序并且在绑定类时无法访问 ActorSystem。

【问题讨论】:

【参考方案1】:

我使用一种可以在任何我想要的地方获得 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();
    

【讨论】:

这也是我最终所做的。现在您必须调用 getDispatcher() 之类的方法,但它是一种改进的解决方案。我试图探索是否有其他方法可以直接注入执行程序而无需任何额外的方法调用。【参考方案2】:

Play 自 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 调度程序动态公开为相应的命名绑定。

【讨论】:

以上是关于如何将自定义 Executor 注入到 play 应用程序中?的主要内容,如果未能解决你的问题,请参考以下文章

在 Play JPA 项目中使用 sbt-native-packager 将自定义文件夹添加到 Docker

如何将自定义代码注入 Swift 中内置类的每个实例化?

如何将自定义格式说明符添加到 fmt

将自定义JAR库添加到Android项目时Delphi10.2中的编译器错误

将自定义 UserManager 注入 Controller Net Core 2.1

将自定义标签注入 Java 客户端的默认 jmx Prometheus 指标