Guice & Scala - Инъекция в зависимости от дженериков
Я пытаюсь создать привязку общего признака с помощью Guice
Посмотрите, как определяется trait
trait Repository[T]
См. реализацию trait
class DomainRepository extends Repository[Domain]
Мой метод configure в DomainPersistenceModule
:
def configure() {
bind(classOf[Repository[Domain]])
.annotatedWith(classOf[DomainDependency])
.to(classOf[DomainRepository])
.in(Scopes.SINGLETON)
}
Переменная, зависимость которой будет введена, равна:
@Inject
@DomainDependency
var repository:Repository[Domain] = _
Инъекция происходит здесь:
val injector:Injector = Guice.createInjector(new PersistenceModule())
val persistenceService:PersistenceService =
injector.getInstance(classOf[DomainPersistenceService])
Ошибка:
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
Я что-то упустил?
Спасибо заранее
Ответы
Ответ 1
Вам нужна привязка TypeLiteral следующим образом:
bind(new TypeLiteral[Repository[Domain]] {})
.annotatedWith(classOf[DomainDependency])
.to(classOf[DomainRepository])
.in(Scopes.SINGLETON)
TypeLiteral
- это специальный класс, который позволяет указывать полный параметризованный тип. По сути, вы не можете создать экземпляр класса с параметром универсального типа.
Также взгляните на этот ответ.
Смотрите "Как внедрить класс с универсальным типом?" в Guice FAQ.
Ответ 2
Как говорит Дэвид, вам нужно TypeLiteral
привязать общий тип (помните, что общие типы стираются только для класса, без параметра типа во время выполнения).
Другая альтернатива - это что-то вроде моей Scala Guice для создания TypeLiteral
, необходимого Guice из Scala Manifest
s. Если вы смешаетесь с чертой ScalaModule
, вы сможете сделать что-то вроде:
bind[Repository[Domain]]
.annotatedWith[DomainDependency]
.to[DomainRepository]
.in(Scopes.SINGLETON)