【问题标题】:How to do Method/Field Injection in Scala using Guice?如何使用 Guice 在 Scala 中进行方法/字段注入?
【发布时间】:2019-10-17 12:58:17
【问题描述】:

我正在尝试在 Scala 中进行方法或字段注入。我正在使用 Play Framework,它使用 Guice 进行注入。我尝试过像这样的字段注入:

@Inject val cache: DefaultSyncCacheApi = null

喜欢详细的here,但每当我尝试测试它时,我都会得到一个NullPointerException。我也尝试过方法注入,例如:

@Inject
def method(id: String, cache: DefaultSyncCacheApi): Boolean = {
   val cachedItem = cache.get(id)
   cachedItem.isDefined
}

也无济于事。我也必须从另一个地方传入缓存。

我也尝试过使用重载方法,分别注入,如:

val cache: DefaultSyncCacheApi //this will not work if it is not an abstract class

@Inject //either injecting here
def methodA(id: String): Boolean = {
   methodB(string, cache)
}

@Inject //or injecting here
def methodB(id: String, cache: DefaultSyncCacheApi): Boolean = {
   //same logic as 'method' above
}

无济于事。是否有明确的方法来进行方法或字段注入而不会导致 NPE?

【问题讨论】:

    标签: scala dependency-injection playframework guice


    【解决方案1】:

    您的问题可能是这些字段被注入太早(在 Guice 设置应用程序之前)。

    所以您可以尝试将所有vals 更改为lazy vals。

    我不得不说我只在完美运行的构造函数中使用注入。你的例子

    class HomeController @Inject()(id: String, cache: DefaultSyncCacheApi)
    

    但是对于id,您的模块中需要一个提供者。因为它是一个字符串,所以你应该命名它。举个例子:

    Module.scala

      @Provides
      @Named("myIdentitfier")
      def provideId(): String = {
        IdCreator.nextId().
      }
    

    HomeController.scala

    class HomeController @Inject()(@Named("myIdentitfier") id: String, cache: DefaultSyncCacheApi)
    

    【讨论】:

    • 仅供参考,懒惰地这样做是行不通的。我也更喜欢通过构造函数来实现,但是这个类正在其他地方实例化,并且需要在整个系统中注入缓存,以将它传递到现在需要它的单个位置。有没有办法在其他地方实例化时使用构造函数注入?
    • 您可以在模块中执行此操作 - 就像我使用“myIdentifier”演示的那样。见github.com/google/guice/wiki/ProvidesMethods
    猜你喜欢
    • 2016-12-03
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    • 2015-10-10
    相关资源
    最近更新 更多