如何使用 Guice 重新初始化控制器中注入的组件?
Posted
技术标签:
【中文标题】如何使用 Guice 重新初始化控制器中注入的组件?【英文标题】:How to reinitialize injected component in controller with Guice? 【发布时间】:2016-01-08 14:41:40 【问题描述】:我有一个控制器:
public class MyController extends Controller
private final AuthChecker authChecker;
@Inject
public MyController(AuthChecker authChecker)
this.authChecker = authChecker;
public Promise<Result> index() throws BusinessException
authChecker
.tokenValue(request().username())
.execute()
.go();
// bla bla bla
我对@987654324@ 有疑问,因为它保留了在每个请求之间未重新初始化的内部状态。这个类的初始化是在它的构造函数中完成的,它只执行一次而不是@Singleton
根据Play's documentation:
每次需要组件时都会创建新实例。如果一个 组件被多次使用,然后,默认情况下,多个实例 的组件将被创建。如果您只想要一个实例 一个组件,那么你需要将它标记为一个单例。
我希望每个请求都告诉 Guice 创建一个新实例。 我该如何解决这个问题?
另外,控制器是单例吗?因为它们似乎在整个应用程序生命周期中只被创建一次。
谢谢。
【问题讨论】:
控制器确实是单例的。因此,每个控制器只创建一个“AuthChecker”实例。换句话说,特定控制器的所有请求共享完全相同的authChecker
实例。您可以调整MyController
的scope 或编写AuthChecker
的无状态版本。 IMO 第二种方法是可取的。
谢谢。是的,阅读您的链接后,第二个似乎更可取。但是我们确定Controllers
是线程安全的吗?如果两个请求同时到达会怎样?
要直接回答您的问题,请注入 Provider<AuthChecker>
而不是普通的 AuthChecker
。
@c4k:写好线程安全控制器是你的责任。在这种情况下,两个请求将并行运行并且彼此独立。如果您的控制器不是线程安全的,例如当您在操作中修改实例变量时,应用程序将变得不确定。如果你愿意,我可以在这个周末的某个时候添加一个例子。请告诉我。
@Roman : 是的,我想要一个例子 ;)
【参考方案1】:
您可以使用 Provider,这意味着 guice 会在您每次访问它时创建一个新实例(如果您的模块中没有另外配置):
public class MyController extends Controller
private final Provider<AuthChecker> authChecker;
@Inject
public MyController(Provider<AuthChecker> authChecker)
this.authChecker = authChecker;
public Promise<Result> index() throws BusinessException
authChecker.get()
.tokenValue(request().username())
.execute()
.go();
// bla bla bla
【讨论】:
以上是关于如何使用 Guice 重新初始化控制器中注入的组件?的主要内容,如果未能解决你的问题,请参考以下文章