To get rid of global state (which goes against the idea of a stateless design) Play introduced DI (I think around v2.4) and in v2.5 it now uses an injected router by default. Google Guice is the default DI framework packaged by Play (you can use others but Guice is the default).
Now (in general) Guice takes the view that creating new instances of a Controller is faster, and more thread safe than using a singleton - see the Guice docs for more.
If you have a need to restrict instances of a controller to only 1 then you can mark it a singleton BUT you have to make it Thread-safe since it will then be shared between threads.
I think the Activator templates could do with a bit more documentation around them to explain why they seem to generate @Singleton
controllers when they do not seem to be needed since it is confusing. HomeController
(in the Play-Scala seed) for example is confusingly declared @Singleton
when it exhibits no case for it.
In general, it is probably best to not use @Singleton
unless you have a fair understanding of immutability and thread-safety. If you think you have a use case for Singleton though just make sure you are protecting any shared state.
In a nutshell, don't use @Singleton
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…