2. Scala Guice - Motivation
Google Guice with Scala is too verbose.
val module = new AbstractModule() {
override def configure() {
bind(classOf[Service]).to(classOf[ServiceImpl])
bind(classOf[BaseDao]).to(classOf[BaseDaoImpl])
}
}
3. Scala Guice - Motivation
Google Guice with Scala is too verbose.
val module = new AbstractModule() {
override def configure() {
bind(classOf[Service]).to(classOf[ServiceImpl])
bind(classOf[BaseDao]).to(classOf[BaseDaoImpl])
}
}
You write less code using Java.
Module module = new AbstractModule() {
@Override
protected void configure() {
bind(Service.class).to(ServiceImpl.class);
bind(BaseDao.class).to(BaseDaoImpl.class);
}
};
4. Scala Guice - Motivation
We can do it better if we use scala.reflect.Manifest[T]
val module = new ScalaModule() {
override def configure() {
bind[Service].to[ServiceImpl]
bind[BaseDao].to[BaseDaoImpl]
}
}
5. Scala Guice - Motivation
We can do it better if we use scala.reflect.Manifest[T]
val module = new ScalaModule() {
override def configure() {
bind[Service].to[ServiceImpl]
bind[BaseDao].to[BaseDaoImpl]
}
}
• But we’ll have to mimic the whole Guice API...
6. Scala Guice - Motivation
We can do it better if we use scala.reflect.Manifest[T]
val module = new ScalaModule() {
override def configure() {
bind[Service].to[ServiceImpl]
bind[BaseDao].to[BaseDaoImpl]
}
}
• But we’ll have to mimic the whole Guice API...
• Only to remove classOf[]
8. Google Guice - internals
Module module = new AbstractModule() {
@Override
protected void configure() {
bind(Service.class).to(ServiceImpl.class);
bind(BaseDao.class).to(BaseDaoImpl.class);
}
};
protected <T> AnnotatedBindingBuilder<T> bind(Class<T>clazz) {
return binder.bind(clazz);
}
The binding starts as soon as method configure is called.
The wiring is no dissociated from its definition.
9. Using Scala to express what you really want
I want to have my binding configuration independent of the binding process.
val services : Configuration = config {
bind[Service].to[ServiceImpl]
}
val daos : Configuration = config {
bind[BaseDao].to[BaseDaoImpl]
}
10. Using Scala to express what you really want
I want to have my binding configuration independent of the binding process.
val services : Configuration = config {
bind[Service].to[ServiceImpl]
}
val daos : Configuration = config {
bind[BaseDao].to[BaseDaoImpl]
}
I want to merge my configuration, without starting the binding.
val mergedConfig = services ++ daos
11. Using Scala to express what you really want
I want to have my binding configuration independent of the binding process.
val services : Configuration = config {
bind[Service].to[ServiceImpl]
}
val daos : Configuration = config {
bind[BaseDao].to[BaseDaoImpl]
}
I want to merge my configuration, without starting the binding.
val mergedConfig = services ++ daos
When I’m ready, I can pass my Configuration to a ScalaModule
class ScalaModule(val configurations: Configuration*) extends AbstractModule {
def configure() = configurations.foreach { c => c.bind(binder()) }
}
12. Scala Guice - internals
trait ConfigurationBuilder {
def config(config: => Unit): Configuration = { ... }
def bind[T](implicit manifT: Manifest[T]): ScalaAnnotatedBindingBuilder[T] = { ... }
}
object ConfigurationBuilder extends ConfigurationBuilder
Scala Guice Builders - mimic Guice API
• ScalaScopedBindingBuilder
• ScalaLinkedBindingBuilder
• ScalaAnnotatedBindingBuilder
def to(impl: Class[_ <: T]): ScalaScopedBindingBuilder = {
// delay call to builder
linkedCommands += { (builder: LinkedBindingBuilder[T]) => builder.to(impl) }
this
}
But real Guice call is recorded for later use
Command pattern with Closures