我刚刚开始,我不认为我理解得很好。据我所知,所有控制器都是在创建路由器时创建的依赖项。然后它们继续运行,直到应用程序终止时路由器终止。如果是这种情况,则宣称它们似乎是多余的。
摆脱全局状态(违背无状态设计的想法)播放引入DI(我认为在v2.4左右)和v2.5中它现在默认使用注入路由器。 Google Guice是Play打包的默认DI框架(您可以使用其他框架,但Guice是默认设置)。
现在(一般而言)Guice认为创建Controller的新实例比使用单例更快,更安全 - 请参阅Guice docs for more。
如果你have a need将控制器的实例限制为只有1,那么你可以将它标记为单例但是你必须使它成为Thread-safe,因为它将在线程之间共享。
我认为Activator模板可以使用更多的文档来解释为什么它们似乎生成@Singleton
控制器,因为它们似乎并不需要它们。例如,HomeController
(在Play-Scala种子中)当它没有表现出任何案例时,令人困惑地宣布@Singleton
。
一般来说,除非你对不变性和线程安全有一个公平的理解,否则最好不要使用@Singleton
。如果你认为你有一个Singleton的用例,只是确保你保护任何共享状态。
简而言之,不要使用@Singleton
。
如果你有一个由路由器实例化的控制器(即默认值),那么它们是隐式单例,因为路由器只存在一次。但是,如果将控制器注入其他位置,除非将其标记为单例,否则仍会获得新实例。
资料来源:https://github.com/playframework/playframework/issues/4508#issuecomment-127820190