1

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 的实例。而这是我无法改变的。但看起来 toProvider 方法不接受 CheckedProvider 类型。

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

4

2 回答 2

5

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


如果你有一个类T和一个检查过的提供者TProvider extends CheckedProvider<T>,你不能只注入T

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

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

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

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

有关我刚刚编写的内容的更多背景信息,请参阅有关 throwing 和 checked providers 的手册。

于 2013-09-25T14:59:21.800 回答
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 方法的实现......

于 2013-09-25T19:26:31.673 回答