Guice And Scala - Injection on Generics Dependencies
I'm trying to create a binding of a generic trait using Guice
See how the trait
is defined
trait Repository[T]
See the trait
implementation
class DomainRepository extends Repository[Domain]
My configure method in DomainPersistenceModule
is:
def configure() {
bind(classOf[Repository[Domain]])
.annotatedWith(classOf[DomainDependency])
.to(classOf[DomainRepository])
.in(Scopes.SINGLETON)
}
The variable whose dependence will be injected is:
@Inject
@DomainDependency
var repository:Repository[Domain] = _
The injection occurs here:
val injector:Injector = Guice.createInjector(new PersistenceModule())
val persisten开发者_JS百科ceService:PersistenceService =
injector.getInstance(classOf[DomainPersistenceService])
The error is:
Caused by: com.google.inject.ConfigurationException: Guice configuration errors:
1) No implementation for repository.Repository<domain.Domain> annotated with @module.annotation.DomainDependency() was bound.
while locating repository.Repository<domain.Domain> annotated with @module.annotation.DomainDependency()
for field at service.persistence.DomainPersistenceService.repository(DomainPersistenceService.scala:19)
while locating service.persistence.DomainPersistenceService
Am I missing something? Thanks in advance
You need a TypeLiteral binding like this:
bind(new TypeLiteral[Repository[Domain]] {})
.annotatedWith(classOf[DomainDependency])
.to(classOf[DomainRepository])
.in(Scopes.SINGLETON)
TypeLiteral
is a special class that allows you to specify a full parameterized type. Basically, you can't instantiate a class with a generic type parameter.
Also, take a look at this answer.
See "How to inject class with generic type?" in the Guice FAQ.
As David says, you need a TypeLiteral
to bind a generic type (remember - generic types are erased to just the class, without the type parameter at run-time).
Another alternative is to something like my Scala Guice library to build the TypeLiteral
s needed by Guice from Scala's Manifest
s. If you mix in the ScalaModule
trait, you would then be able to do something like:
bind[Repository[Domain]]
.annotatedWith[DomainDependency]
.to[DomainRepository]
.in(Scopes.SINGLETON)
精彩评论