Scaldi — is Scala dependency injection library. Basically Scala already have everything you need for dependency injection. But still some things can be made easier. Goal of the project is to provide more standard and easy way to make dependency injection in Scala projects consuming power of the Scala language. With Scaldi you can define your application modules in pure Scala without any annotations or XML.
class AppModule extends Module {
bind [Printer] to new StreamPrinter
bind [PrintStream] to Console.out
}
class ConfigModule extends Module {
binding identifiedBy "userName" to "Bob"
binding identifiedBy "prefix" and "console" to "Howdy, "
}
object MyApp extends App with Injectable {
implicit val modules = new AppModule :: new ConfigModule
val printer = inject [Printer]
printer print "Welcome!"
}
trait Printer {
def print(str: String): Unit
}
class StreamPrinter(implicit inj: Injector) extends Printer with Injectable {
val userName = inject [String] (identified by "userName" and by default "Anonimous")
val prefix = inject [String] ("console" and "prefix" and by default "Hello, ")
val writer = inject [PrintStream] (by default Console.err)
def print(str: String) {
writer.println(prefix + userName + " - " + str)
}
}
I demonstrated you one of many Scaldi flavours. If something bothers you in this example, don’t be afraid, Scaldi has also many other flavours that can match your taste.
For example, you can define you bindings by defining vals and defs. So example above can also be written as:
class AppModule extends Module {
lazy val printer: Printer = new StreamPrinter
lazy val consoleStream: PrintStream = Console.out
}
class ConfigModule extends Module {
val userName = "Bob"
binding identifiedBy "prefix" and "console" to "Howdy, "
}
You can even avoid dependency on Injector in your own classes, if you like:
class AppModule extends Module {
bind [Printer] to StreamPrinter(
userName = inject (identified by "userName" and by default "Anonimous"),
prefix = inject ("console" and "prefix" and by default "Hello, "),
writer = inject (by default Console.err)
)
bind [PrintStream] to Console.out
}
// ...
case class StreamPrinter(userName: String, prefix : String, writer:PrintStream) extends Printer {
def print(str: String) {
writer.println(prefix + userName + " - " + str)
}
}
Among many useful features of Scaldi, I would like to highlight most important ones:
You are given choice to decide how you want to make dependency injection:
StaticModule which can contribute it’s own
bindings to the module composition, but can’t consume other bindings from the composition
Module which has some side effect during initialization process, but can also consume all
other bindings from the module composition
Ability to define your bindings in number of ways
bind [Server] as 'http to new HttpServer
lazy val http: Server = new HttpServer
Expressive and type-safe injection Scala DSL:
inject [Server] (identified by 'http and by default new HttpServer)