简体   繁体   English

使用Play2.4和scala的Google Guice的循环依赖性错误

[英]Circular Dependency Error for Google Guice with Play2.4 and scala

My application uses Play 2.4 with Scala 2.11 .I started transforming my existing code to make use of Google Guice that comes with Play 2.4 . 我的应用程序使用Play 2.4和Scala 2.11 。我开始转换现有代码以使用Play 2.4附带的Google Guice

When I run my code after making the first set of changes , I found Some DAOs in my code are failing with circular dependency error. 当我在进行第一组更改后运行代码时,我发现代码中的某些DAO失败并出现循环依赖性错误。

For example I have two DAOs 例如,我有两个DAO

class BookDAO @Inject()
(protected val personDAO : PersonDAO,
 @NamedDatabase("mysql")protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
...
...
val personId = //some id
personDAO.get(personId)
}

class PersonDAO @Inject()
(protected val bookDAO : BookDAO,
 @NamedDatabase("mysql")protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
...
...
val bookName= //some id
personDAO.getByName(bookName)
}

I got the below error while trying to access either BookDAO or PersonDAO 尝试访问BookDAO或PersonDAO时出现以下错误

Tried proxying schema.BookDAO to support a circular dependency, but it is not an interface.
  at schema.BookDAO.class(Books.scala:52)
  while locating schema.BookDAO

Can someone help me resolving this error . 有人可以帮我解决这个错误。

Thanks in advance 提前致谢

Quick solution 快速解决方案

Inject a Provider instead: 注入Provider

class BookDAO @Inject()(personDaoProvider: Provider[PersonDAO], ...)
extends HasDatabaseConfigProvider[JdbcProfile] {
  val personDAO = personDaoProvider.get
  def person = personDAO.get(personId)
}

And the same for BookDAO . BookDAO This will work out of the box. 这将开箱即用。 Guice already "knows" how to inject Providers. Guice已经“知道”如何注入提供商。


Better approach 更好的方法

Decouple the class definition from the implementation. 将类定义与实现分离。 See Mon Calamari's answer. 见Mon Calamari的回答。

Define your dependencies as follows and pull up all needed methods from class to trait: 按如下方式定义依赖项,并将所有需要的方法从类转移到trait:

@ImplementedBy(classOf[BookDao])
trait IBookDao {
  // abstract defs
}

class BookDao @Inject()(protected val personDAO: IPersonDao, protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] with IBookDao {
}

@ImplementedBy(classOf[PersonDao])
trait IPersonDao {
  // abstract defs
}

class PersonDao @Inject()(protected val bookDAO: IBookDao, protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] with IPersonDao {
}

As you can see, each dao implements a trait and all dao dependencies are injected by trait . 如您所见,每个dao实现了一个特征,并且所有dao依赖项都由trait注入。 This gives Guice possibility to inject a proxy class and resolve a circular dependency issue. 这使Guice可能注入代理类并解决循环依赖问题。

More details on playframework scala dependency injection here . 有关详细信息playframework scala依赖注入这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM