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

在没有说明原因的情况下,有人想要一个老式的Play框架web服务,不想使用依赖注入,也不想依赖Google的Guice。在游戏2.8.x中仍然有可能吗

与当前播放示例一起,建议将其作为“典型”HomeController.scala:

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发表评论,但你可以通过使用“正确”(非测试)很容易地修改他的例子
控制器组件
,由上下文中的
内置组件提供

整个例子看起来