如何使用scala将实例传递给ServiceInjector特征?

时间:2015-07-06 07:47:21

标签: scala guice

我正在遵循com.googlegroups.google-guice http://markmail.org/message/ljnhl6rstverrxuj

的建议
Well, it's actually almost as referred to you in the link from the other answer:

http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/

class MyClient {
  @Inject val toBeInjected: AnotherClass = toBeInjected // !!
}

trait ServiceInjector {
  ServiceInjector.inject( this )
}

object ServiceInjector {
  private val injector = Guice.createInjector( Array[Module]( new YourModule ) )
  def inject( obj: AnyRef ) = injector.injectMembers( obj )
}

Usage:

val client = new MyClient with ServiceInjector

or:

class InjectedMyClient extends MyClient with ServiceInjector

但是我对Scala很新,并试图找出如何使用以下模式进行依赖注入,当Guice模块本身需要引用从其他地方传入的实例时。

但是因为traits不能有构造函数,Companion对象看起来我也不会被搞砸了?

package au.id.rleach.overmind.guice

import com.google.inject.{Provides, Guice, Binder, Module}
import org.slf4j.Logger
import org.spongepowered.api.service.ServiceManager
import org.spongepowered.api.world.TeleportHelper
import org.spongepowered.api.{GameRegistry, Game}
import org.spongepowered.api.plugin.PluginManager
import org.spongepowered.api.scoreboard.ScoreboardBuilder
import org.spongepowered.api.service.event.EventManager

class OModule(val game: Game, val logger: Logger, val pluginManager: PluginManager, val serviceManager: ServiceManager, val eventManager: EventManager, val gameRegistry: GameRegistry, val teleportHelper: TeleportHelper) extends Module {

  override def configure(binder: Binder): Unit = {
    binder.bind(classOf[Game]).toInstance(game)
    binder.bind(classOf[Logger]).toInstance(logger)
    binder.bind(classOf[PluginManager]).toInstance(pluginManager)
    binder.bind(classOf[ServiceManager]).toInstance(serviceManager)
    binder.bind(classOf[EventManager]).toInstance(eventManager)
    binder.bind(classOf[GameRegistry]).toInstance(gameRegistry)
    binder.bind(classOf[TeleportHelper]).toInstance(teleportHelper)
    //bind(classOf[File]).annotatedWith(new ConfigDirAnnotation(true)).toInstance(Loader.instance.getConfigDir)
  }
}

trait ServiceInjector {
  ServiceInjector.inject(this)
}

object ServiceInjector {
  private val injector = Guice.createInjector(
//####
    new OModule()//compilation error.
//####
  )
  def inject(obj: AnyRef) = injector.injectMembers(obj)
}

我意识到该对象在第一次使用时正在被初始化,这是在我将一个实例副本传递给OModule之后,但我似乎无法找到将它们传递给对象的方法。

2 个答案:

答案 0 :(得分:1)

由于我正在使用Scala,因此我不再使用DI框架,因为Scala已经具有原生的DI支持。这称为蛋糕模式。有很多可用的资源,例如blogpost from Cake Solutions

在ScalaDays 2014和Devoxx 2014上,Dick Wall还展示了一种更轻量级的DI解决方案,他称之为Parfait Pattern。这两场会谈都可以在Parleys.com上查看

如果你真的想使用DI框架,Scaldi是一个很好看的Scala框架,它使用Scala功能,当然你也可以继续使用Spring或Guice。

答案 1 :(得分:1)

我不确定这个:

@Inject val toBeInjected: AnotherClass = toBeInjected

根据我的经验不起作用。它必须是var而非val和初始值null

@Inject var toBeInjected: AnotherClass = null

我创建了demo on GitHub这是Play-Scala模板,index方法更改如下:

class Application extends Controller {

  @Inject var ws: WSClient = null

  def index = Action.async {
    ws.url("http://google.com").get.map(r => Ok(r.body))
  }

}

运作良好。注入到字段中,而不是作为构造函数参数。 traits可以使用相同的技术。