问题
I have experience of developing a web-based application with Scala and Play. Play supports Guice out of the box, so it is very easy to do DI with Play.
I'm currently working on a Scala project that is not a web application and it does not use Play. I want to dynamically inject the config object into a few places. How do I do this?
If it is necessary to use some library to do DI, what library is good for this purpose? Any sample code? Is it possible to implement this with plain Scala not using any external library? When I google "Scala DI without Play", all the results are with Play.
Thanks in advance!
回答1:
Play has nothing to do with dependency injection. It's handled by Guice - widespread Java DI library.
To grasp the main concepts of Guice I recommend you to read this source.
回答2:
I like to use Macwire.
Setup
Add this line to your build.sbt
file:
libraryDependencies += "com.softwaremill.macwire" %% "macros" % "2.3.2" % Provided
and then reload.
Notice that the scope is Provided
, so it doesn't add any runtime overhead. It uses macros to do its job in compile time. This means that you get a compile-time dependency injection, and if you are missing a dependency you will find it out as soon as possible - with a compile-time error, rather than getting a runtime exception.
Code Example
- Let's define two services, X and Y, with some dependencies, A, B, and C, so we can use them later:
case class A()
case class B()
case class C()
case class X(a: A, b: B)
case class Y(c: C)
- Now let's wire our dependencies at the end of the world (near the main function):
import com.softwaremill.macwire._
lazy val a = wire[A]
lazy val b = wire[B]
lazy val c = wire[C]
lazy val x = wire[X]
lazy val y = wire[Y]
- The compiler will translate the code above to the following code:
lazy val a = new A()
lazy val b = new B()
lazy val c = new C()
lazy val x = new X(a, b)
lazy val y = new Y(c)
This is basically the implementation with plain Scala code, as you asked in your post.
Changing Dependencies
A nice thing here, is that when one of the services changes by adding/removing a dependency, your wiring code will remain the same.
For example, let's change service Y to also require B as a dependency.
- Our services and dependencies will look like this:
case class A()
case class B()
case class C()
case class X(a: A, b: B)
case class Y(b: B, c: C)
The wiring code will remain the same.
The compiler will translate the wiring code to:
lazy val a = new A()
lazy val b = new B()
lazy val c = new C()
lazy val x = new X(a, b)
lazy val y = new Y(b, c)
回答3:
I'm not that sure, but I think you can still use the
"com.google.inject" % "guice" % "4.2.2"
and implement something like this.
class Module extends com.google.inject.AbstractModule {
protected def configure() = {
// Example Usage:
bind(classOf[ClassNameToInjected]).asEagerSingleton()
}
}
Hope it will helps.
来源:https://stackoverflow.com/questions/55536189/how-to-use-dependency-injection-in-scala-without-play-framework