Guice中作用域注释和范围实例之间的区别

时间:2017-02-12 08:38:14

标签: java dependency-injection guice

在Guice中,当您指明某个实例的生命周期时,您将使用类似bind(Applebees.class).in(Singleton.class);的范围注释。 或者您似乎可以使用范围实例,如

bind(UserPreferences.class)
      .toProvider(UserPreferencesProvider.class)
      .in(ServletScopes.REQUEST);

正式Guice建议使用前一种方法,因为前一种方法允许我们重用Module类。 但我不确定这一点。我的假设是这样的,所以请检查这是否正确。

范围实例是Servelet的术语,因此如果采用范围实例而不是范围注释,则Module类仅适用于Servelet。另一方面,如果您使用作用域注释,则可以重用Module类,除非您放弃Guice。

所以,这是对的吗?你能查一下吗?

1 个答案:

答案 0 :(得分:1)

我相信你的理解是正确的,但对于哪种复用会受到影响有一点微妙。

你可能是指the Guice wiki on Scopes(强调我的)的这篇文章:

  

in()子句接受像RequestScoped.class这样的范围注释以及Scope之类的ServletScopes.REQUEST个实例:

bind(UserPreferences.class)
    .toProvider(UserPreferencesProvider.class)
    .in(ServletScopes.REQUEST);
     

注释是首选,因为它允许模块在不同类型的应用程序中重用。 例如,@RequestScoped对象可以限定为Web应用程序中的HTTP请求,也可以作用于API服务器中的RPC。

即使使用Guice的特定于servlet的范围,您也可以在Scope实例ServletScopes.REQUEST@RequestScoped annotation之间进行选择,并相应地在in(Scope scope)in(Class scopeAnnotation)之间进行选择(请参阅{{ 3}})。几乎每个范围都应该有相应的注释,因为它们对类和@Provides方法特别有用。

重要的是要在这里意识到总是一个ScopedBindingBuilder实际上实现了作用域行为(具体来说,包装一个未作用域的Provider,以便它可以在适当的条件下返回已经返回的实例)。要将注释与Scope实例相关联,您需要确保模块调用Scope instance,它接受​​Scope注释类和Scope实例;对于Servlets,bindScope

@Override
protected void configure() {
  bindScope(RequestScoped.class, REQUEST);
  bindScope(SessionScoped.class, SESSION);
  // ...
}

那么使用in(Class scopeAnnotation)有什么好处?当绑定到Scope实例时,你正在告诉Guice你想要使用哪个Scope实例,而不是让用户有机会使用bindScope将注释绑定到不同的Scope实例。在上面加粗的示例中,您可以想象使用相同的模块而不使用实际的Guice servlet扩展(注释除外),但这只有在绑定到注释类然后调用{{1}时才有可能。你自己。如果使用bindScope绑定,则需要更改该行或编写新模块。

这对您自己的自定义范围实例和注释尤为重要,因为它允许您在整个应用程序中一致地更改范围界定行为:

in(Scope)