我正在查看 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
如果您想了解有关此概念的内容:
我希望这能解决问题!如果您有问题,请务必提问!
关于Scala (Play 2.4.x) 如何使用@inject() 注解调用类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31343401/