我正在看 Play 邮件程序中的鳞状代码示例: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
但是,当我们尝试运行需要该引用的任何内容时,仍然会为null。
我正在阅读我可以在@Inject上找到的所有内容
([警告] [rant]我并不是这样的编译器魔术迷,因为这个确切的原因-伏都教魔术直到停止工作才是美好的,然后似乎没人知道如何解决它。[/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
具有Play的Application
作为依赖项将被注入(inject),因为Play提供了一些预绑定(bind)的预设,例如Application
和ActorSystem
。这是可能的,因为 Play !框架使用
DependencyInjectedRoutes
。如果要在Controller外部创建Actor,则需要在模块类中指定该Actor,但此link和link中对此进行了说明。还有一个概念,就是在 Controller 内部使用
Traits
,然后稍后将特征与实现类连接在一起,但我认为这有点太复杂了。如果您希望这种编写应用程序的方法有一些好处并成功案例,这里是一个很好的资源:https://softwareengineering.stackexchange.com/a/19204/164366
如果您想对这个概念有所了解:
我希望这可以清除一切!如果您有任何疑问,请一定要提问!
关于Scala( Play 2.4.x)如何使用@inject()批注调用类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31343401/