[英]Dependency injection with Scala
I was searching a way of doing dependency injection in Scala kind of like Spring or Unity in C# and I found nothing really interesting. 我正在寻找一种在Scala中进行依赖注入的方式,比如Spring中的Spring或Unity,我发现没有什么真正有趣的。
So I decided to make my implementation and ask you what do you think because it's surprising me that nothing like this has been done before. 所以我决定进行实施,然后问你的想法是什么,因为令我惊讶的是之前没有做过这样的事情。 Maybe my implementation have lot's of issues in real life also.
也许我的实现在现实生活中也有很多问题。
So here is an example: 所以这是一个例子:
trait Messenger {
def send
}
class SkypeMessenger extends Messenger {
def send = println("Skype")
}
class ViberMessenger extends Messenger {
def send = println("Viber")
}
I want here to inject everywhere in my app the implementation configured in only one place: 我想在我的应用程序中随处注入仅在一个地方配置的实现:
object App {
val messenger = Inject[Messenger]
def main(args: Array[String]) {
messenger.send
}
}
Note the Inject[Messenger] that I define like below with the config I want (prod or dev): 注意我使用我想要的配置(prod或dev)定义的Inject [Messenger]如下所示:
object Inject extends Injector with DevConfig
trait ProdConfig {
this: Injector =>
register[Messager](new SkypeMessager)
register[Messager](new ViberMessager, "viber")
}
trait DevConfig {
this: Injector =>
register[Messager](new ViberMessager)
register[Messager](new ViberMessager, "viber")
}
And finally here is the Injector which contains all methods apply and register: 最后这里是包含所有方法的Injector并注册:
class Injector {
var map = Map[String, Any]()
def apply[T: ClassTag] =
map(classTag[T].toString).asInstanceOf[T]
def apply[T: ClassTag](id: String) =
map(classTag[T].toString + id).asInstanceOf[T]
def register[T: ClassTag](instance: T, id: String = "") = {
map += (classTag[T].toString + id -> instance)
instance
}
}
To summaries: 总结:
What do you think? 你怎么看?
You code looks a lot like dependency injection in Lift web framework. 您的代码看起来很像Lift Web框架中的依赖注入。 You can consult Lift source code to see how it's implemented or just use the framework.
您可以查阅Lift源代码以了解它是如何实现的,或者只是使用框架。 You don't have to run a Lift app to use its libraries.
您无需运行Lift应用程序即可使用其库。 Here is a small intro doc .
这是一个小型的介绍文档 。 Basically you should be looking at this code in Lift:
基本上你应该在Lift中查看这段代码:
package net.liftweb.http
/**
* A base trait for a Factory. A Factory is both an Injector and
* a collection of FactorMaker instances. The FactoryMaker instances auto-register
* with the Injector. This provides both concrete Maker/Vender functionality as
* well as Injector functionality.
*/
trait Factory extends SimpleInjector
You can also check this related question: Scala - write unit tests for objects/singletons that extends a trait/class with DB connection where I show how Lift injector is used. 您还可以检查以下相关问题: Scala - 使用DB连接扩展特征/类的对象/单例的单元测试,其中显示了如何使用Lift注入器。
Thanks guys, 多谢你们,
So I make my answer but the one from Aleksey was very good. 所以我做出了答案,但是Aleksey的答案非常好。
I understand better the Cake Pattern with this sample: 我更了解这个样本的蛋糕模式:
https://github.com/freekh/play-slick/tree/master/samples/play-slick-cake-sample https://github.com/freekh/play-slick/tree/master/samples/play-slick-cake-sample
Take a look also to the other implementations without DI and compare: 看看没有DI的其他实现并比较:
https://github.com/freekh/play-slick/tree/master/samples/ https://github.com/freekh/play-slick/tree/master/samples/
And so the cake pattern doesn't have a centralized config like we can have with my shown lift style DI. 所以蛋糕模式没有像我们所展示的升降式DI那样的集中配置。 I will anyway use the Cake pattern as it fits well with Slick.
无论如何,我会使用Cake模式,因为它非常适合Slick。
What I didn't like with Subcut is the implicits everywhere. 我对Subcut不喜欢的是各地的暗示。 I know there is a way to avoid them but it looks like a fix to me.
我知道有一种方法可以避免它们,但它看起来像是对我的修复。
Thanks 谢谢
To comment on MacWire , you are right that you could just use new
- and that's the whole point :). 要评论MacWire ,你是对的,你可以使用
new
- 这就是重点:)。 MacWire is there only to let you remove some boilerplate from your code, by not having to enumerate all the dependencies again (which is already done in the constructor). MacWire只允许您从代码中删除一些样板,而不必再次枚举所有依赖项(已在构造函数中完成)。
The main idea is that you do the wiring at "the end of the world", where you assemble your application (or you could divide that into trait-modules, but that's optional). 主要的想法是你在“世界末日”进行布线,在那里组装你的应用程序(或者你可以把它分成特征模块,但这是可选的)。 Otherwise you just use constructors to express dependencies.
否则,您只需使用构造函数来表示依赖关系。 No magic, no frameworks.
没有魔法,没有框架。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.