【问题标题】:How to implement the lifecycle callbacks of play framework(2.5.x)play framework(2.5.x)的生命周期回调如何实现
【发布时间】:2016-09-30 05:43:16
【问题描述】:

我正在尝试学习游戏框架。我想在我的应用程序中实现播放框架的生命周期回调。现在我看到使用下面的 GlobalSettings 可以轻松完成:

object Global extends GlobalSettings {

  override def onStart(app: Application) {
    Logger.info("Application has started")
  }  

  override def onStop(app: Application) {
    Logger.info("Application shutdown...")
  }  

}

但它已在 play framework(2.5.x) 中被弃用。他们为onStart 回调和onStoponError 提供了急切的绑定,还有其他机制。我查看了 2.5.x 版本的文档并看到如下代码:

import com.google.inject.AbstractModule
import com.google.inject.name.Names

class Module extends AbstractModule {
  def configure() = {

    bind(classOf[Hello])
      .annotatedWith(Names.named("en"))
      .to(classOf[EnglishHello]).asEagerSingleton

    bind(classOf[Hello])
      .annotatedWith(Names.named("de"))
      .to(classOf[GermanHello]).asEagerSingleton
  }
}

但不幸的是,我无法理解它。与使用 GlobalSettings 一样,实现生命周期回调很容易。假设我将在生命周期回调中实现一个 Logger 信息。没有复杂的代码。
如何在 2.5.x 中实现启动、停止和错误回调??

【问题讨论】:

    标签: scala playframework application-lifecycle playframework-2.5


    【解决方案1】:

    一般而言,将这些机制从GlobalSettings 事物中移开也意味着您不再全局注册此类“回调”,而是将它们绑定到组件/类。这样做的好处是,某个组件的初始化和关闭可以直接在相应的类内部发生。但是,如果您有想要在启动(或关闭)时运行的代码,而这些代码未绑定到特定组件(例如日志记录、启动检查等),您将必须为它们创建新类并将它们绑定到您的模块中。

    请注意,在后一种情况下,您通常将各个类绑定为急切的单例(以确保它们被实例化),而在前一种情况下,这些类被实例化为依赖关系树的一部分。

    启动:在依赖注入容器管理的任何类的构造函数中运行代码。

    1. 在模块中绑定类

      bind(classOf[Hello]).to(classOf[EnglishHello]).asEagerSingleton
      
    2. 将代码放入构造函数

      class EnglishHello extends Hello {
        println("hello")
      }
      

    请注意,asEagerSingleton 本身不是必需的。我假设您使用 Guice 作为 DI 提供者,您可以在此处阅读更多相关信息:https://github.com/google/guice/wiki/Scopes

    关闭:在任何需要运行关闭代码的类中,注册一个生命周期回调。

    1. 在模块中绑定类

      bind(classOf[Hello]).to(classOf[EnglishHello]).asEagerSingleton
      
    2. 注册生命周期回调(并注入ApplicationLifecycle

      class EnglishHello @Inject() (lifecycle: ApplicationLifecycle) extends Hello {
        lifecycle.addStopHook { () =>
          Future.successful(connection.stop())
        }
      }
      

    请注意,您可能希望将这些类限定为单例,否则您最终会为每个实例注册停止挂钩 - 根据您的停止挂钩的作用,这可能是您想要的。在此处阅读更多信息:https://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection#Stopping/cleaning-up

    错误:实现您自己的HttpErrorHandler。基本思想是您实现一个具有许多将由 Play 调用的方法的类!关于各自的错误。这记录在这里:https://www.playframework.com/documentation/2.5.x/ScalaErrorHandling

    【讨论】:

    • 我不理解这一行 bind(classOf[Hello]).to(classOf[EnglishHello]).asEagerSingleton 。你能详细解释一下 Hello 类是什么以及为什么使用 to(classOf[EnglishHello]) 以及通过编写这一行来完成什么?我是这个框架的新手。你能用更简单的方式解释一下吗??
    • 这意味着每当您请求Hello 的实例(例如class Bye @Inject() (h: Hello) { .. })时,都会注入(传入)EnglishHello 的实例。在 guice 的创建者的演讲中了解更多关于依赖注入如何有益的信息:youtube.com/watch?v=0iSB0L9avmg
    • 如何对采用 ApplicationLifecycle 参数的类进行单元测试?
    猜你喜欢
    • 2016-08-05
    • 2016-11-17
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    相关资源
    最近更新 更多