如何在guice中绑定到CheckedProvider?

时间:2013-09-24 22:26:24

标签: java guice

Guice提供了一种绑定到提供者的方法:

    bind(A.class).toProvider(AProvider.class);

虽然如果我的提供者需要抛出异常,那么CheckedProvider似乎是一个正确的基础接口:

    public interface ConfigCheckedProvider<T> extends CheckedProvider<T> {
        T get() throws ConfigException;
    }

    public AProvider implements ConfigCheckedProvider<A> { ... }

但是现在我的一些类需要注入A的实例。这我无法改变。但看起来像Provider方法不接受CheckedProvider类型。

如何使用基于CheckedProvider的提供商注入实例而不是提供商

2 个答案:

答案 0 :(得分:5)

根据您的要求,我将发表评论作为答案。


如果您有课程T和已检查的提供者TProvider extends CheckedProvider<T>,则无法仅注入T

@Inject
SomeClass(T t) {  // Won't work
    ...
}

如果您使用普通Provider<T>,就可以。这是故意做的。当创建对象可能因特定类型的异常而失败时,需要经过检查的提供程序,并且此失败必须由用户代码处理。普通提供商没有这样的功能。

Provider<T>不允许从get()方法中抛出已检查的异常,并且它抛出的任何未经检查的异常都可能被包装到ProvisionException中,因此您无法可靠地捕获异常。此外,如果您直接注入T并且提供程序的get()方法失败,那么在注入期间您将收到错误,这可能会导致难以理解的堆栈跟踪(特别是如果您不使用Injector直接)甚至他们的缺席。

经过检查的提供程序允许您从提供程序中抛出预先声明的异常类型,并且保证将这些异常原样传递给在已检查的提供程序上调用get()的代码。通过这种方式,您可以可靠地捕获它们,但作为回报,您将失去注入由提供程序直接创建的对象的能力。

请参阅关于投掷和检查提供商的this manual,了解我刚才所写的更多背景信息。

答案 1 :(得分:0)

很明显,我所要求的是故意不提供的。但是,可以编写自己的已检查提供程序,该提供程序将实现Provider,因此可用于toProvider绑定。

例如,我提供了以下Checked Provider可能有意义:

public abstract class MyCheckedProvider<T, E extends Exception> 
                      implements Provider<T> {

    public abstract T getChecked() throws E;

    @Override
    public T get() {
        try {
            return getChecked();
        } catch (Exception e) {
            throw new ProvisionException("Checked provider threw exception", e );
        }
    }
}

使用此MyProvider,AProvider可能如下所示:

public class AProvider extends MyCheckedProvider<A, ConfigException> {
    @Override
    public A getChecked() throws ConfigException {
        ...
    }
}


bind(A.class).toProvider(AProvider.class);

只有在提供程序出现问题时才要抛出ProvisionExceptions,所有这些都有效。对于其他逻辑,MyProvider显然应该有get方法的其他实现......