Scala (Play 2.4.x) 如何使用@inject() 注解调用类

标签 scala playframework annotations inject

我正在查看 play-mailer 中的鳞状代码示例:https://github.com/playframework/play-mailer

它基本上是这样的:

class MyComponent @Inject() (mailerClient: MailerClient) {
   ...
}

很简单,它编译时不兼容

然后我尝试“调用”它,但似乎没有一种方法可以满足编译器或获取 mailerClient 的工作实例。
object AnObject {
  val mailer = new MyComponent
  def sendEmail = mailer.doStuff
}

[info] Compiling 1 Scala source to ...
[error] /SomeOne/SomePath/SomeFile.scala:30: not enough arguments for constructor MyComponent: (mailerClient: play.api.libs.mailer.MailerClient) MyComponent.
[error] Unspecified value parameter mailerClient.
[error]   val mailer = new MyComponent
[error]                ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed

我虽然可能因为这个而接近了:

How does @Inject in Scala work

这表明以下语法可以通过删除 @Inject 来工作。从构造函数并将其放置在字段上。
@Inject var mailerClient: MailerClient = null

然而,当我们尝试运行任何需要该引用的东西时,我们仍然会得到空值。

我正在阅读我在@Inject 上可以找到的所有内容

([警告] [咆哮]出于这个确切原因,我不喜欢这样的编译器魔法——巫术魔法非常棒,直到它停止工作,然后似乎没有人知道如何修复它。[/rant] [/警告] )

但我真正想知道的是如何正确、安全、有效地使用它。

最佳答案

由于您在原始 GitHub 存储库上关闭了您的问题,我不知道这个答案是否仍然必要,但由于您不完全了解 DI 框架的使用,我发现学习这项技能非常重要,我会尝试在这里解释它并列出一些好处。

首先,您实例化实例的方式不会让 DI 框架有机会注入(inject)您的依赖项。由于new是一个语言关键字,DI 不能干扰,并且你的类需要的依赖项不能被注入(inject)。它是通过构造函数或字段注入(inject)来完成的。我将主要关注构造函数注入(inject),因为这是 scala 世界中的“标准”。

如果您使用 @Injected 指定构造函数参数注释,您基本上是在告诉 DI 框架从容器中解决此依赖关系。 DI 框架会在其容器内查找该对象的条目。如果它不存在,它会创建它(并在这个过程中解决它的依赖关系),如果它被注解为 @Singleton还保存此实例以供将来使用。大多数 DI 框架要求您在大多数情况下指定起始类,但因为您使用的是 Play!框架这不是必需的。当您想在 Controller 中使用特定模块时,您可以这样做:

import javax.inject.Inject

import play.api.mvc.Controller

class Test @Inject() (val dependency: FooClass) extends Controller {
  ...
}

在这种情况下 FooClass是要注入(inject) Controller 的依赖项的类名。假设 FooClass有玩的Application作为依赖项,这将被注入(inject),因为 Play 提供了几个预先绑定(bind)的预设,例如 Application还有ActorSystem .

这是可能的,因为 Play!框架使用 DependencyInjectedRoutes .如果您要在 Controller 之外创建一个 Actor,您需要在模块类中指定它,但这在 link 中有解释。这个link .

还有一个使用Traits的概念在 Controller 内部,然后将特征与实现类连接在一起,但我认为现在这有点太复杂了。

如果您想了解这种编写应用程序的方法的一些好处和成功案例,这里有一个很好的资源:https://softwareengineering.stackexchange.com/a/19204/164366

如果您想了解有关此概念的内容:
  • https://www.playframework.com/documentation/2.4.x/ScalaAkka
  • https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection
  • https://www.playframework.com/documentation/2.4.x/ScalaCompileTimeDependencyInjection

  • 我希望这能解决问题!如果您有问题,请务必提问!

    关于Scala (Play 2.4.x) 如何使用@inject() 注解调用类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31343401/

    相关文章:

    scala - Play 模板仅在使用括号调用时有效

    斯卡拉玩!使用 anorm 或 ORM

    java - 在哪里放置@PreAuthorize,在接口(interface)或实现上

    scala - 在 Scala 中实现通用向量

    scala - 使用半径过滤器查询针对不同的索引/查询具有不同的半径

    java - Play 2 - 尚未定义默认的 EBean 服务器

    java - 如何使用 Hibernate 正确注释 List<Interface>?

    xml - 条件依赖注入(inject)

    scala - 关闭 Scala 秋千架

    scala - 如何使用新的反射 API 来判断数组的组件类型是否符合类型参数?