2017-05-29 38 views
0

我想實現一個Guice模塊,它將一個適配器綁定到一個命名參數,但爲了創建這個適配器,它需要實例化另一個類,它也需要注入參數。Guice綁定一個類和它的適配器

這裏是Scala的例子:

trait Service 

class UserService @Inject()(@Named(value = "foo") foo: String) extends Service 

trait Adapter 

class AdapterImpl(service: Service) extends Adapter 

class AdapterRef(val adapter: Adapter) 


class Module extends AbstractModule { 
    override def configure(): Unit = { 
    val fooValue = "bar" 

    bind(classOf[String]) 
     .annotatedWith(Names.named("foo")) 
     .toInstance(fooValue) 


    val userService = new UserService(fooValue)  //It should be instantiated by Guice somehow 

    bind(classOf[AdapterRef]) 
     .annotatedWith(Names.named("userService")) 
     .toInstance(new AdapterRef(new AdapterImpl(userService))) //Thats kinda ok 
    } 
} 

能有人指出正確的方向?

謝謝

的Gabor

+0

什麼是錯誤? – rethab

+0

沒有錯誤。我需要一個可以替換這行的解決方案:「val userService = new UserService(fooValue)」,因爲我希望系統將所有依賴關係注入到該行中。 –

+0

您創建一個注入器並傳入模塊。然後你從注入器獲得實例。 Google文檔:https://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Guice.html – rethab

回答

0

您可以將模塊,它可以讓你刪除綁定內使用Provides方法。這是我在Scala的最大努力,所以如果語法不正確,請告訴我。

@Provides() @Singleton() def provideAdapterRef(service: Service): AdapterRef = { 
    return new AdapterRef(new AdapterImpl(service)) 
} 

請注意使用單例模仿你的例子使用toInstance。如果你不需要它總是提供相同的實例,我會建議刪除範圍,並讓它每次都創建一個新範例。

另一種解決方案是使用Provider。這要求您在模塊中保留綁定的修改版本並創建一個額外的類,但如果您的提供者更復雜,它可能是一個更乾淨的解決方案。

//Can inject UserService as well, or provide annotations to configure which 
//implementation of Service you get if you have more than one. 
class UserServiceProvider @Inject()(service: Service) extends Provider[AdapterRef] { 
    override def get(): AdapterRef { 
     return new AdapterRef(new AdapterImpl(service)) 
    } 
} 

然後你就可以改變你的模塊中結合

bind(classOf[AdapterRef]) 
    .annotatedWith(Names.named("userService")) 
    .toProvider(classOf[UserServiceProvider]) 
    .in(classOf[Singleton]) 

注意這裏使用的in(Singleton),以複製toInstance行爲。