Play 2.4 添加模块而不是插件

Posted

技术标签:

【中文标题】Play 2.4 添加模块而不是插件【英文标题】:Play 2.4 Adding Module instead of Plugin 【发布时间】:2015-10-18 08:30:56 【问题描述】:

我有一个 Play 2.3 应用程序,我正在迁移到 Play 2.4,我正在处理关于将插件迁移到模块的警告之一。我在这里关注此文档:

https://www.playframework.com/documentation/2.4.x/PluginsToModules

现在我的应用程序中有几个问题,其中包含一些 Akka 演员。到目前为止,这是我对插件所做的:

  class MyPlugin extends Plugin 

    // I get the current Application
    val app = play.api.Play.current

    // On start of the plugin, I call my initializers
    def onStart: Unit = 
      super.onStart()
      doInitialize(app)
    
  

现在在我的 doInitialize 例程中,我对所需的不同服务进行初始化。我稍后将这些服务公开为一个特征,并将这个特征混合在我需要服务引用的地方。例如,我的控制器看起来像:

object Application extends Controller with MyServices 

  ....

MyServices 在哪里

trait MyServices 

  def myActorRef: ActorRef
  ...
  ...

现在应该如何将此设置迁移到使用对整个应用程序影响不大的模块?当我从插件迁移到模块时,我应该把 onStart 方法的内容放在哪里也不清楚!

编辑:我尝试了以下方法:

sealed trait MyComp
class MyCompImpl @Inject() (lifecycle: ApplicationLifecycle) extends MyComp 
  val application = MyConfig(play.api.Play.current)

  // initialize upon start
  Initializer.doInitialize(application)

  // destroy upon stop
  lifecycle.addStopHook(() => 
    Future.successful  Initializer.destroyConfig(application) 
  )

我的模块定义如下:

class MyModule extends Module 

  override def bindings(environment: play.api.Environment, configuration: Configuration): Seq[Binding[_]] = 
    logger.info(s"registering bindings")
    Seq(
      bind[MyComp].to[MyCompImpl].eagerly()
    )
  

现在失败了,原因是:

CreationException: 无法创建注入器,看到如下错误:

1) Error injecting constructor, java.lang.RuntimeException: There is no started application
  at com.config.MyCompImpl.<init>(MyModule.scala:25)
  while locating com.config.MyCompImpl

每次将 Play 应用程序升级到较新版本时,都会感到很痛苦!

【问题讨论】:

【参考方案1】:

您需要考虑 2.4 中的另一项更改:“Removing GlobalSettings”:

任何需要在启动时发生的事情现在都应该发生在 依赖注入类的构造函数。一个班会表演 当依赖注入框架加载它时它的初始化。 如果你需要急切的初始化(因为你需要执行一些 应用程序实际启动之前的代码),定义一个渴望 绑定。

在这个页面上 - https://www.playframework.com/documentation/2.4.x/PluginsToModules - 你有:

bind[MyComponent].to[MyComponentImpl]

在你的例子中你需要使用

bind[MyComponent].to[MyComponentImpl].asEagerSingleton

并且代码doInitialize(app)必须在MyComponentImpl的构造函数中运行,就像

class MyComponentImpl extends MyComponent 
  initialize() 
  def initialize() = 
     //initialize your app
  

【讨论】:

感谢您的回复!如果我需要在启动期间访问底层应用程序对象的 Play 框架怎么办?我应该如何注射?我已经用我尝试过的方法编辑了我的问题!你能看一下并对此发表评论吗? 您是否尝试过像“sparkr”所说的那样注入应用程序?好吧,是你:) 是的,我吃了自己的狗粮!无论如何,感谢您的参与!【参考方案2】:

我设法解决了这个问题:

sealed trait MyComp
class MyCompImpl @Inject() (app: Application, lifecycle: ApplicationLifecycle) extends MyComp 
  val application = Myconfig(app)

  // initialize upon start
  Initializer.doInitialize(application)

  // destroy upon stop
  lifecycle.addStopHook(() => 
    Future.successful  Initializer.destroyConfig(application) 
  )

【讨论】:

以上是关于Play 2.4 添加模块而不是插件的主要内容,如果未能解决你的问题,请参考以下文章

插件如何在 play 2.4 中使用注入和对象而不是类

heroku 部署与 play framework 1.2.4 和自己的安全模块

如何使用模块而不是插件插入播放生命周期?

Play Framework:如何在用户注册时使用 Secure 模块自动登录?

Play 2.4 - 在 Eager 单例模块中使用 Ebean

如何以编程方式将 Play 2.4 模块的执行限制为单个主机?