斯卡拉(播放的2.4.x)如何调用类@Inject()注释 [英] Scala (Play 2.4.x) How to call a class with @inject() annotation
问题描述
我期待在从播放邮件的鳞屑code例如: https://开头的github .COM / playframework /播放,邮件</A>
I'm looking at the scaly code example from play-mailer: https://github.com/playframework/play-mailer
它去基本上是这样的:
class MyComponent @Inject() (mailerClient: MailerClient) {
...
}
足够简单,它编译没有符合
simple enough and it compiles without compliant
然后我试着然而,呼叫,并似乎没有被满足编译器或获取mailerClient的工作实例的方式。
Then I try to "call" it however and there doesn't appear to be a way to satisfy the compiler OR get a working instance of 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
不过,我觉得我可能已经得到了接近得益于这样的:
I though I might have gotten close thanks to this:
这表明以下语法可能会被从构造函数删除 @Inject
,并把它放在一个领域的工作。
Which indicated that the following syntax might work by removing the @Inject
from the constructor and placing it on a field.
@Inject var mailerClient: MailerClient = null
但是,我们尝试运行任何需要的参考,我们仍然得到空的时刻。
However the moment we try to run anything that needs that reference we still get null.
我在读的一切,我可以找到@Inject
I'm reading everything I can find on @Inject
的([警示] [咆哮]我不是这个确切原因的编译器魔术这样的风扇 - 巫术是美好的,直到它停止工作,然后,似乎没有人对如何解决任何想法它[/咆哮] [/警告])的
但我真正想知道的是如何正确地使用它,安全而有效。
but what I really want to know is how to use it properly, safely and effectively.
推荐答案
由于您关闭您的问题对原GitHub库,我不知道这个答案仍然是必要的,但因为你没有完全了解使用一个DI框架,我觉得非常重要的学习这个技能,我会试着在这里解释它,并列出一些好处。
Since you closed your issue on the original GitHub repo, I don't know if this answer is still necessary but since you don't fully understand the use of a DI framework and I find it incredibly important to learn this skill, I'll try to explain it here and list some benefits.
首先,你实例化你的实例并不会给DI框架有机会注入你的依赖的方式。由于新
是一门语言的关键字,DI不能干涉,你需要为你的类的依赖性,不能注射。它是如何做是通过构造函数或字段注入。我将主要集中在构造函数注入,因为这是在世界上阶的标准。
First off, the way you are instantiating your instance doesn't give the DI framework a chance to inject your dependencies. Since new
is a language keyword, DI can't interfere and the dependencies you need for your class can't be injected. How it is done is through constructor or field injection. I'll mainly focus on constructor injection because that is "standard" in the scala world.
如果您指定的 @Injected
注释的构造函数的参数,你基本上是告诉DI框架来解决从容器这种依赖性。该DI框架去,并查找其容器内的那个对象的条目。如果不存在,它会创建它(并解决其在进程的依赖),如果它与 @Singleton
注释还可以节省这种情况下以备将来使用。大多数DI框架,要求你在大多数情况下,指定一个起始类,但由于您使用的游戏!框架,这是没有必要的。当你想使用一个特定模块控制器里面,你可以这样做:
If you specify a constructor argument with the @Injected
annotation, you are basically telling the DI framework to resolve this dependency from the container. The DI framework goes and looks for an entry of that object inside its container. If it doesn't exists, it will create it (and resolve its dependencies in the process) and if it's annotated with @Singleton
also save this instance for future use. Most DI frameworks require you to specify a starting class in most cases but because you are using Play! Framework this is not necessary. When you want to use a particular module inside your controller you can do this:
import javax.inject.Inject
import play.api.mvc.Controller
class Test @Inject() (val dependency: FooClass) extends Controller {
...
}
在这种情况下, FooClass
是要注入到控制器的依赖的类名。比方说, FooClass
具有播放的应用
作为一个依赖,这将被注入,因为游戏提供了一些pre-保税$ p $的pset像应用
也 ActorSystem
。
In this case FooClass
is the class name of the dependency you want to inject into your controller. Let's say FooClass
has Play's Application
as a dependency this will be injected, because Play provides a couple pre-bonded presets like Application
but also ActorSystem
.
这是可能的,因为游戏!框架使用 DependencyInjectedRoutes
。如果你到一个控制器之外创建一个演员,你需要指定一个模块类中但在此说明的链接这链接。
This is possible because Play! Framework uses DependencyInjectedRoutes
. If you were to create an Actor outside of an Controller you would need to specify that inside a module class but that is explained in this link and this link.
还有使用性状
控制器内,然后以后将它们连接起来的特点与实现类的概念,但我认为这是一个有点太复杂了,现在。
There is also a concept of using Traits
inside your controller and then later on wiring together the traits with the implementation classes but I think that is a bit too complicated for now.
如果你想要一些好处和更迭的故事来书写应用这种方法,这里是一个很好的资源:<一href=\"http://programmers.stackexchange.com/a/19204/164366\">http://programmers.stackexchange.com/a/19204/164366
If you want some benefits and succes stories to this method of writing applications, here is a good resource: http://programmers.stackexchange.com/a/19204/164366
如果你想要的东西,以这个概念为:
If you want something to read on this concept:
- 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
- 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
我希望这将清除的东西了!如果您有疑问,请不要问!
I hope this clears things up! If you have question, please do ask!
这篇关于斯卡拉(播放的2.4.x)如何调用类@Inject()注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!