java - 是否每个 Play 框架 Web 请求都使用新的依赖注入(inject) Controller 实例处理,但是静态 Controller 方法呢?

标签 java playframework dependency-injection frameworks

我的问题是关于 Java Play 框架中 Controller 的生命周期, Controller 是有状态实例还是使用静态方法的无状态实例,以及如何在 Controller 代码中使用依赖注入(inject)。

是否每个网络请求都由 Play Controller 类的新实例处理,即 Controller 是否可以将状态存储在字段中,例如注入(inject)到 Controller 构造函数中的服务? (在文档的什么地方解释了?)

关于 Controller 是有状态实例还是使用静态方法的无状态 Controller ,Play 框架自早期版本以来是否发生了变化(如果是,在哪个版本?)

您在哪里可以看到有关在使用有状态 Controller 时框架如何将服务注入(inject) Controller 实例的代码示例以及如何将服务注入(inject)静态 Controller 方法的示例?

关于后者,即注入(inject)静态方法,我想这要么必须是框架将要添加的方法的参数,要么如果不可能的话,您可能不得不在方法中使用服务定位器例如实例化一个 Guice 模块类,然后在静态 Controller 方法中使用“injector.getInstance”。

以下页面的“依赖注入(inject) Controller ”部分涉及此主题:

https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection

但是,它没有显示代码如何将服务实际注入(inject)到 Controller 实例中(但可能与其他“组件”的方式相同,即使用@Inject 注释)并且当然它目前没有显示如何使用 DI静态 Controller 方法。

我对这些事情感到困惑,因为我没有找到明确说明我的问题的文档,而且我还在一本 Play 书中(从 2013 年开始)读到 Controller 方法应该被编程为无状态的并且 Controller 方法应该是静态的.

但是,当现在使用激活器为具有最新 Play 版本 (2.4.6) 的 Java 生成 Play 应用程序时,我可以看到生成的 Controller 方法 (Application.index) 不是静态的。 此外,在以下文档页面中, Controller 方法不是静态的: https://www.playframework.com/documentation/2.4.x/JavaActions

这很令人困惑,因为了解每个请求是否由 Controller 实例处理(即是否可以使用状态)是非常基础的,我认为这应该在有关 Controller /操作的页面上更好地记录比没有解释它的当前文档(上面的链接页面)。

关于依赖注入(inject)的文档在提到“静态路由生成器”的“依赖注入(inject) Controller ”部分涉及静态和非静态方法的主题,但我认为应该更好地解释它,包括代码示例。

如果 Play 团队中的某个人正在阅读这个问题,那么请在上面的链接页面中添加一些信息,例如,请务必提及(如果我的理解是正确的话)在以前版本的 Play 中, Controller 方法是静态的,并且对于这些版本你永远不应该在字段中存储状态,但在以后的版本中(从版本 x 开始?)每个请求都由 Controller 的一个实例处理,因此可以使用状态(例如框架注入(inject)的构造函数参数)。

还请提供有关与静态 Controller 方法一起使用的注入(inject)以及每个请求一个实例注入(inject)有状态 Controller 实例的代码示例。

依赖注入(inject)页面中的“组件生命周期”部分只提到了“组件”,但我认为它也应该明确说明 Controller 生命周期及其注入(inject),因为它是与所有开发人员清楚沟通的基础和重要知识避免因对是否有状态的误解而导致的错误。

最佳答案

Is each web request handled by a new instance of a Play controller class, i.e. can a controller store state in fields such as services injected into the controller constructor? (where in the documentation is it explained?)

据我所知, Controller 默认是单例对象。这没有明确记录,但暗示 Controller 实例被重用。查看migration guide for Playframework 2.4 :

The injected routes generator also supports the @ operator on routes, but it has a slightly different meaning (since everything is injected), if you prefix a controller with @, instead of that controller being directly injected, a JSR 330 Provider for that controller will be injected. This can be used, for example, to eliminate circular dependency issues, or if you want a new action instantiated per request.

另外,检查 this commend made by James Roper (扮演核心提交者)关于 Controller 是否是单例:

Not really - if using Guice, each time the controller is injected into something, a new instance will be created by default. That said, the router is a singleton, and so by association, the controllers it invokes are singleton. But if you inject a controller somewhere else, it will be instantiated newly for that component.

这表明默认情况下是在响应请求时重用 Controller 实例,如果您希望每个请求都有一个新的操作,则需要使用迁移指南中描述的语法。但是...因为我更倾向于证明和尝试事情而不是仅仅相信,我创建了一个简单的 Controller 来检查该声明:

package controllers

import play.api._
import play.api.mvc._

class Application extends Controller {

  def index = Action {
    println(this)
    Ok(views.html.index("Your new application is ready."))
  }

}

对此操作执行多个请求会为所有请求打印相同的对象identity。但是,如果我在我的路线上使用 @ 运算符,我开始为每个请求获得不同的身份。所以,是的,默认情况下 Controller 是(某种)单例

Has the Play framework changed since earlier versions (and if so, at what version?) regarding if controllers are stateful instances or stateless controllers with static methods?

默认情况下,Play 一直提倡无状态 Controller ,如您所见the project homepage :

Play is based on a lightweight, stateless, web-friendly architecture.

那没有改变。因此,您不应该使用 Controller 的字段/属性来保存随时间/请求而变化的数据。相反,只需使用 Controller 的字段/属性来保留对同样无状态的其他组件/服务的引用。

Where can you see code examples about how the framework injects services into a controller instance when stateful controller is used and example of how to inject services into a static controller method?

关于代码示例,Lightbend templates repository是要去的地方。以下是一些在 Controller 级别使用依赖注入(inject)的示例:

  1. https://github.com/adrianhurt/play-api-rest-seed
  2. https://github.com/knoldus/playing-reactive-mongo
  3. https://github.com/KyleU/boilerplay

不支持静态方法的依赖注入(inject),这就是为什么 Playframework 仍然提供 old apis与静态方法一起使用。这里的经验法则是:在 DI 和静态方法之间进行选择。尝试同时使用两者只会给您的应用程序带来复杂性。

关于java - 是否每个 Play 框架 Web 请求都使用新的依赖注入(inject) Controller 实例处理,但是静态 Controller 方法呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34863486/

相关文章:

android - Dagger 2 : Injecting to Activities from multiple subcomponents

java - 在 Glassfish 中将 Gemini 蓝图部署到 Felix

java - 将字符串和文件发送到 InputStream

java - Visual Studio Code 无法处理 Java

java - 如何验证 Play Framework 1 中的图片上传?

java - Akka 已弃用警告 [ Prop ] Play Framework 2.2.X

gwt - 延迟绑定(bind)失败

java - Mockito 模拟不适用于此方法。难道我做错了什么?

scala - 验证带有复选框元组的映射表单

java - Spring:如何在运行时更改接口(interface)实现