OptionalBinding 使用 Guice 避免用户绑定

Posted

技术标签:

【中文标题】OptionalBinding 使用 Guice 避免用户绑定【英文标题】:OptionalBinding using Guice to avoid binding by users 【发布时间】:2020-01-31 11:30:20 【问题描述】:

遵循OptionalBinder的文档

一种用于绑定可选值的 API,可以选择使用默认值。 OptionalBinder 有两个作用:

    它允许框架定义一个可能会或可能不会被用户绑定的注入点。 它允许框架提供可由用户更改的默认值。

我正在尝试跟进上面的第一点,为此我有以下设置:

interface Reporting<R>  // service to be bind optionally

class InternalServiceImpl implements InternalService 
    @Inject
    Reporting reporting;
    ... // use this in a method


public class FrameworkModule extends AbstractModule 
   protected void configure() 
     OptionalBinder.newOptionalBinder(binder(), Reporting.class);
   

在用户模块中 (class UserWorkingModule) 如果我不提供绑定,例如

bind(new TypeLiteral<Reporting<ReportingEvent>>()).to(ReportingImpl.class).in(Singleton.class);

应用程序无法启动并显示以下日志:

1) No implementation for Reporting was bound.   while locating Reporting
    for field at InternalServiceImpl.reporting(InternalServiceImpl.java:21) at
FrameworkModule.configure(FrameworkModule.java:55) (via modules: UserWorkingModule -> FrameworkModule)

是否仍然必须在UserWorkingModule 中为Reporting 提供绑定?

【问题讨论】:

在一个问题上,我用最少的代码分享了哪些有效,哪些无效。我不明白投反对票的原因! 【参考方案1】:
bind(new TypeLiteral<Reporting<ReportingEvent>>()).to(ReportingImpl.class).in(Singleton.class);

是通用Reporting&lt;ReportingEvent&gt;的绑定,而

OptionalBinder.newOptionalBinder(binder(), Reporting.class);

实际上是指定原始类型Reporting。相反,您想使用 newOptionalBinder 和 specifies a TypeLiteral arg 的重载,以便在可选请求和绑定中讨论相同的内容:

OptionalBinder.newOptionalBinder(binder(), new TypeLiteral<Reporting<ReportingEvent>>());

没有这个,你基本上是在说“任何绑定到报告都会满足这个要求”,甚至像Reporting&lt;Object&gt; 这样的东西 - 如果你绑定多个会发生什么?


另一方面,如果你真的想允许任何Reporting 类型的绑定(这是你的错误所暗示的,那么相反的事情是错误的:而不是绑定到原始Reporting,你指定了而是通用 impl。将 bind() 调用更改为“这实际上仅适用于原始请求”:

bind(Reporting.class).to(ReportingImpl.class).in(Singleton.class);

【讨论】:

感谢您抽出时间来回答。你的意思是说在FrameworkModule 中使用OptionalBinder.newOptionalBinder(binder(), new TypeLiteral&lt;Reporting&lt;ReportingEvent&gt;&gt;());,我不需要在UserWorkingModule 中绑定? UserWorkingModule 不在你的问题中,除了堆栈跟踪,所以我真的不能说。这可能是 bind(..).to(..) 调用所在的类的名称吗?如果是这样,您仍然需要在任何一种方法下,但您需要 newOptionalBinder(..) 和 bind(..).to(..) 同意,因为他们现在不同意(并且那些进一步应该同意注入站点,在 InternalServiceImpl 中,也许还有其他)。 是的,我在“如果我不提供诸如“之类的绑定的用户模块中提到,它是放置bind(..).to(..)的类的名称。我没有得到你说的部分“在任何一种方法下你仍然需要它”。这不是问题中链接的文档点(1)吗?至于我发布的实际问题,我的意思只是 - 是否仍然必须为 UserWorkingModule 中的报告提供绑定? 哦,我明白了-我理解您的问题是在问“为什么我会收到此错误”(答案是“您的代码与您的请求不匹配”),而不是“如果这种方法使它成为可选的,为什么它似乎仍然是必需的”,它有一个单独的答案。我会相应地更新答案。【参考方案2】:

在使用OptionalBinder 时,您实际上并没有指定绑定。使用OptionalBinder时仍需要指定默认绑定试试:

     OptionalBinder.newOptionalBinder(binder(), Reporting.class)
        .setDefault()
        .to(ReportingImpl.class);

【讨论】:

以上是关于OptionalBinding 使用 Guice 避免用户绑定的主要内容,如果未能解决你的问题,请参考以下文章

guice整合struts2,guice的使用

Guice源码学习基本原理

使用 Guice 实现 Restlet

TestNG 中使用 Guice 来进行依赖注入

使用 Guice 注入通用实现

Guice、Peaberry 和 ServletModule