我正在试图弄清楚如何将我的课程与Google Guice一起注入play.api.Plugin。 我已经实现了Guice与我的控制器一起工作,它工作得很好。
我用:
"com.google.inject" % "guice" % "4.0-beta",
"com.tzavellas" % "sse-guice" % "0.7.1"
当需要Controller实例时,Global中的getControllerInstance方法将通过注入器加载适当的实现。
全局:
object Global extends GlobalSettings {
/**
* Currently we only want to load a different module when test.
*/
private lazy val injector = {
Logger.info("Is Test: "+Play.isTest)
Play.isTest match {
case true => Guice.createInjector(new TestModule)
case false => Guice.createInjector(new CommonModule)
}
}
override def onStart(app: Application) {
Logger.info("Application has started")
}
override def onStop(app: Application) {
Logger.info("Application shutdown...")
}
override def getControllerInstance[A](clazz: Class[A]) = {
Logger.info("getControllerInstance")
injector.getInstance(clazz)
}
}
常见:
package modules
import com.tzavellas.sse.guice.ScalaModule
import services.{CallServiceImpl, CallService}
/**
* User: jakob
* Date: 11/5/13
* Time: 10:04 AM
*/
class CommonModule extends ScalaModule {
def configure() {
bind[CallService].to[CallServiceImpl]
}
}
class TestModule extends ScalaModule {
def configure() {
// Test modules!
}
}
控制器:
@Singleton
class StatsController @Inject()(callService: CallService) extends Controller with securesocial.core.SecureSocial with ProvidesHeader {
def doSomething = {
callService.call()
}
}
现在我想将相同的服务注入到我的插件中,但我无法使用全局实现,因为插件没有加载 getControllerInstance
class CallerPlugin (application: Application) extends Plugin {
val secondsToWait = {
import scala.concurrent.duration._
10 seconds
}
val defaultInterval = 60
val intervalKey = "csv.job.interval"
val csvParserEnabled = "csv.job.enabled"
val newDir = "csv.job.new.file.path"
val doneDir = "csv.job.done.file.path"
var cancellable: Option[Cancellable] = None
override def onStop() {
cancellable.map(_.cancel())
}
override def onStart() {
// do some cool injection of callService here!!!
import scala.concurrent.duration._
import play.api.libs.concurrent.Execution.Implicits._
val i = current.configuration.getInt(intervalKey).getOrElse(defaultInterval)
cancellable = if (current.configuration.getBoolean(csvParserEnabled).getOrElse(false)) {
Some(
Akka.system.scheduler.schedule(0 seconds, i minutes) {
callService.call()
})
} else None
}
}
我想应该有一种方法在onStart方法中以某种方式实现注入,并且可能有一些很好的简单方法来做到这一点,但我无法弄明白。 谢谢!
答案 0 :(得分:0)
如果我理解你的问题,你就会想知道如何实例化和使用Guice注入器。嗯,这很简单:
val injector = Guice.createInjector(new CommonModule)
val callService = injector.getInstance(classOf[CallService])
就像你有一个CallServiceImpl
的实例。如果你看看你的Global.scala,这正是你在那里所做的。我没有使用过Play插件,所以我不确定你是如何实例化它们的,但是我认为一种更惯用的方法是将onStart
注入此插件,而不是将它放在插件的CallService
中。 CallerPlugin
的参数(就像你对控制器所做的那样)。这样你就可以将依赖注入的责任传递给树了,所以理想情况下你最终只能使用一个注入器(可能在Global
中)。
答案 1 :(得分:0)
从我发现到目前为止,实现此目的的最佳方法是在Global.onStart()
中设置插件的依赖性。
public class Global extends GlobalSettings{
public Injector injector = createInjector();
private Injector createInjector(){
return Guice.createInjector(new SomeGuiceModule());
}
@Override
public void onStart(Application application) {
CallerPlugin plugin = application.plugin(CallerPlugin.class);
plugin.setCallService(injector.getInstance(CallService.class));
}
}
确保插件号低于10000
。全局有10000
,因此,您的插件将在Global.onStart()
被调用之前启动。