Scala 在没有依赖注入的情况下使用框架?
在没有说明原因的情况下,有人想要一个老式的Play框架web服务,不想使用依赖注入,也不想依赖Google的Guice。在游戏2.8.x中仍然有可能吗 与当前播放示例一起,建议将其作为“典型”HomeController.scala:Scala 在没有依赖注入的情况下使用框架?,scala,playframework,Scala,Playframework,在没有说明原因的情况下,有人想要一个老式的Play框架web服务,不想使用依赖注入,也不想依赖Google的Guice。在游戏2.8.x中仍然有可能吗 与当前播放示例一起,建议将其作为“典型”HomeController.scala: package controllers import javax.inject._ import play.api.mvc._ class HomeController @Inject() (val controllerComponents: Controller
package controllers
import javax.inject._
import play.api.mvc._
class HomeController @Inject() (val controllerComponents: ControllerComponents) extends BaseController {
def index = Action {
Ok("It works!")
}
}
我想要的代码是相同的,但没有@Inject()(类似于我上次在2016年使用Play 2.4.0时的代码)?当年我的代码是这样的:
package controllers
import play.api.mvc.{Action, AnyContent, Controller}
object TestController {
def index:Action[AnyContent] = Action {
Ok("It used to work.")
}
}
控制台:
[info] Compiling 1 Scala source to /Volumes/.../play-scala-seed/target/scala-2.13/classes ...
[error] p.a.h.DefaultHttpErrorHandler -
! @7ef69nl6l - Internal server error, for (GET) [/test/] ->
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) Could not find a suitable constructor in controllers.TestController. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
at controllers.TestController.class(TestController.scala:3)
while locating controllers.TestController
for the 4th parameter of router.Routes.<init>(Routes.scala:33)
at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:137):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$4)
1 error]
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:210)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:141)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:296)
at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:186)
at akka.stream.impl.fusing.MapAsync$$anon$30.onPush(Ops.scala:1261)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:541)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:423)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:624)
at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:501)
at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:599)
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Could not find a suitable constructor in controllers.TestController. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
at controllers.TestController.class(TestController.scala:3)
while locating controllers.TestController
for the 4th parameter of router.Routes.<init>(Routes.scala:33)
at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:137):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$4)
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:543)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:159)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
at com.google.inject.Guice.createInjector(Guice.java:87)
at com.google.inject.Guice.createInjector(Guice.java:78)
at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:200)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:155)
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
at play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:189)
at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
[info]正在将1个Scala源代码编译到/Volumes/../play Scala seed/target/Scala-2.13/classes。。。
[错误]p.a.h.DefaultHttpErrorHandler-
! @7ef69nl6l-内部服务器错误,用于(GET)[/test/]->
play.api.UnexpectedException:意外异常[CreationException:无法创建注射器,请参阅以下错误:
1) 在controllers.TestController中找不到合适的构造函数。类必须有一个(并且只有一个)用@Inject注释的构造函数,或者一个非私有的零参数构造函数。
位于controllers.TestController.class(TestController.scala:3)
查找controllers.TestController时
用于router.Routes的第四个参数。(Routes.scala:33)
at play.api.inject.RouteProvider$.bindingsFromConfiguration(BuiltinModule.scala:137):
绑定(类router.Routes to self)(通过模块:com.google.inject.util.modules$OverrideModule->play.api.inject.guice.GuiceableModuleConversions$$anon$4)
1错误]
play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:210)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:141)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:296)
在play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:186)
在akka.stream.impl.fusing.mapsync$$anon$30.onPush(Ops.scala:1261)
在akka.stream.impl.fusing.graphinterpler.processPush(graphinterpler.scala:541)
在akka.stream.impl.fusing.graphinterpler.execute(graphinterpler.scala:423)
在akka.stream.impl.fusing.graphinterptershell.runBatch(ActorGraphInterpreter.scala:624)
在akka.stream.impl.fusing.graphinterperterShell$AsyncInput.execute(ActorGraphExplorer.scala:501)中
在akka.stream.impl.fusing.GraphinterperterShell.processEvent(ActorGraphExplorer.scala:599)中
原因:com.google.inject.CreationException:无法创建注入器,请参阅以下错误:
1) 在controllers.TestController中找不到合适的构造函数。类必须有一个(并且只有一个)用@Inject注释的构造函数,或者一个非私有的零参数构造函数。
位于controllers.TestController.class(TestController.scala:3)
查找controllers.TestController时
用于router.Routes的第四个参数。(Routes.scala:33)
at play.api.inject.RouteProvider$.bindingsFromConfiguration(BuiltinModule.scala:137):
绑定(类router.Routes to self)(通过模块:com.google.inject.util.modules$OverrideModule->play.api.inject.guice.GuiceableModuleConversions$$anon$4)
1错误
位于com.google.inject.internal.Errors.ThrowCreationExceptionIferErrorSexist(Errors.java:543)
在com.google.inject.internal.InternalInjectorCreator.InitializeStatly上(InternalInjectorCreator.java:159)
在com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)上
位于com.google.inject.Guice.createInjector(Guice.java:87)
位于com.google.inject.Guice.createInjector(Guice.java:78)
at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:200)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:155)
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
在play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:189)
在播放时.utils.Threads$.withContextClassLoader(Threads.scala:21)
有没有一个简单的方法可以让你保持老样子——不去上学
我承认,但并不完全理解。我假设我的问题与中已删除的静态路由有关。事实上,
StaticRoutesGenerator
需要将控制器作为单例对象。举个例子,也许使用可以让您更接近您以前的习惯,但是仍然需要注入ControllerComponents
。从技术上讲,通过打开Compile
classpath并像这样使用,可能会做一些不明智的事情
和相应的最小ApplicationLoader
class MyApplicationLoader extends ApplicationLoader {
def load(context: ApplicationLoader.Context): Application = {
new BuiltInComponentsFromContext(context) {
override def httpFilters: Seq[EssentialFilter] = Nil
lazy val homeController = new _root_.controllers.HomeController
lazy val router: Router = new _root_.router.Routes(httpErrorHandler, homeController)
}.application
}
}
这样一来,HomeController
,虽然仍然是一个类,但现在完全是硬连线的,在ApplicationLoader
中只创建了一个实例
就我个人而言,我会建议大家不要玩这种把戏,并且相信为什么游戏会远离单例,例如,可测试性等等。实际上,StaticRoutesGenerator一直以来都是需要控制器作为单例对象的。举个例子,也许使用可以让您更接近您以前的习惯,但是仍然需要注入
ControllerComponents
。从技术上讲,通过打开Compile
classpath并像这样使用,可能会做一些不明智的事情
和相应的最小ApplicationLoader
class MyApplicationLoader extends ApplicationLoader {
def load(context: ApplicationLoader.Context): Application = {
new BuiltInComponentsFromContext(context) {
override def httpFilters: Seq[EssentialFilter] = Nil
lazy val homeController = new _root_.controllers.HomeController
lazy val router: Router = new _root_.router.Routes(httpErrorHandler, homeController)
}.application
}
}
这样一来,HomeController
,虽然仍然是一个类,但现在完全是硬连线的,在ApplicationLoader
中只创建了一个实例
就我个人而言,我会建议大家不要玩这样的把戏,并且相信为什么游戏会远离单身,例如,可测试性,等等。我的名声不允许我对by发表评论,但你可以通过使用“正确”(非测试)很容易地修改他的例子
控制器组件
,由上下文中的内置组件提供
整个例子看起来