2013-12-13 53 views
3

这将是一个关于如何让绑定工作的问题,但是在清理我的示例以准备发布后,我已经设法使其工作 - 问题是我不知道为什么这个工程:用Scala Guice绑定一个对象到一个对象

import org.specs2.mutable._ 
import com.google.inject.{ Inject, Module, Binder, Guice } 
import net.codingwell.scalaguice.ScalaModule 

object InjectorSpec extends Specification { 
    val injector = Guice.createInjector(new ScalaModule() { 
    def configure() { 
     bind[Message].toInstance(MessageImpl) 
     bind[MessageService.type].toInstance(MessageService) // This line makes it work? 
    } 
    }) 

    trait Message { 
    val body: String 
    } 

    object MessageImpl extends Message { 
    val body: String = "Hello!" 
    } 

    object MessageService { 
    @Inject 
    val message: Message = null 

    def get = message.body 
    } 

    "MessageService" should { 
    "Inject Message Implementation" in { 
     MessageService.get mustEqual "Hello!" 
    } 
    } 
} 

最初我只是绑定类型被注入(注入MessageImpl消息)。一路上,我拿起了服务的第二个绑定,没有注入(所以我不明白绑定是必需的)。任何人都可以解释这里发生了什么,如果这是继续进行的正确方法?

+0

https://pbs.twimg.com/media/ A5HdRB-CIAAM3Ri.png:大* scnr * –

+0

@StefanKunze确切! :) – matthewrk

回答

3

所以问题在于,guice不会搜索您的程序,并找到您在任何地方加载的任何类中的所有@Inject点。相反,需要给它一些路径来找到你想要注入东西的对象。通常,这是通过使用吉斯的方式照顾,因为标准模式是:

val injector = Guice.createInjector(/* stuff */) 
val main = injector.getInstance(classOf[Main]) 
main.mainMethod() 

吉斯上的Main实例,你问它做/获取,并在所有递归执行注射执行注射东西@Inject编成main

就你而言,其中一个陈述也有效;我说“其中之一”,因为虽然我可以告诉你如何注入到java我不完全清楚scala编译器如何将scala伴随对象编译为java类。 (也就是说,我不知道是否message通过一些线程Singleton模式最终是在Java级别上称为MessageService$类或实例变量静态变量,与被实例化MessageService$只有一次)

requestInjection(MessageService) 
requestStaticInjection(MessageService.type) 

toInstance声明起作用的原因是Guice在创建注射器时自动对传递到toInstance的所有注射进行注射。 (如果你创建一个“生产模式”注射器,所有东西都绑定为单件,所以约束.asEagerSingleton也将在注射器上进行注射)

+0

啊哈,我认为这将是沿着这些线。 @Inject和requestInjection的使用似乎比我的代码基础上直接引用注入器更清晰了? – matthewrk

+2

那么,理想情况下,你只需要引用'injector'一次,只为你的主类调用'getInstance'一次,然后所有东西都从那里注入。 斯卡拉伴侣对象将事情搞砸了一点,因为它们是从java的角度来看这些在Guice之外创建的单例对象。现在,这很好,但是当你有这些Guice没有创建的东西时,麻烦来了,你想让Guice注入东西。我不喜欢scala-guice风格(我所有的Guice经验都是用java编写的),但我认为解决方案是永远不要将@Inject注入到伴随对象中。 –

+1

也就是说,如果你需要'@Inject'的singleton对象,使它们成为'trait's或'class'es并绑定它们.in(classOf [Singleton])'在Guice里面;不要在需要注入东西的地方使用伴侣对象。 –