ThrowingProvider
Guiceは(プロバイダによる)インスタンス生成中の例外をうまくハンドリングできない。
プロバイダ実装はRuntimeExceptionのみを投げることが可能である(訳注:チェック例外は利用できない)。
プロバイダの呼び出し側は、それが投げる例外をキャッチすることができない。なぜなら、それらはProvisionExceptionによってラップされているからである。
- プロバイダを利用せず、インスタンスに直接注入しようとすると、そのインスタンスの生成に失敗する可能性がある。
- Exceptions cannot be advertised in the API.
ThrowingProvidersはプロバイダの代替であり、チェック例外を投げることができる。
- API consistent with Provider.
- Scopable
- Standard binding DSL
ThrowingProviderインターフェースはProviderと同様であるが、一般例外タイプを持つ。
public interface ThrowingProvider<T,E extends Exception> {
T get() throws E;
}それぞれのアプリケーション例外について、ThrowingProviderを拡張するインターフェースを作成するとよい。 我々のニュースウィジェットアプリケーションではFeedUnavailableExceptionを投げるFeedProviderを作成した。
public interface FeedProvider<T> extends ThrowingProvider<T, FeedUnavailableException> { }WordlNewsFeedProviderとSportsFeedProviderの実装を作成し、それらをモジュール内にてThrowingProviderBinderを使ってバインドする。
public static class FeedModule extends AbstractModule {
protected void configure() {
ThrowingProviderBinder.create(binder())
.bind(FeedProvider.class, BbcFeed.class)
.annotatedWith(WorldNews.class)
.to(WorldNewsFeedProvider.class)
.in(HourlyScoped.class);
ThrowingProviderBinder.create(binder())
.bind(FeedProvider.class, BbcFeed.class)
.annotatedWith(Sports.class)
.to(SportsFeedProvider.class)
.in(QuarterHourlyScoped.class);
}
}最後にFeedProviderをアプリケーション全体に渡って注入する。 そのget()呼び出しではいつでもFeedUnavailableExceptionをハンドリングすべきことをコンパイラが教えてくれる。
public class BbcNewsWidget {
private final FeedProvider<BbcFeed> worldNewsFeedProvider;
private final FeedProvider<BbcFeed> sportsFeedProvider;
@Inject
public BbcNewsWidget(
@WorldNews FeedProvider<BbcFeed> worldNewsFeedProvider,
@Sports FeedProvider<BbcFeed> sportsFeedProvider) {
this.worldNewsFeedProvider = worldNewsFeedProvider;
this.sportsFeedProvider = sportsFeedProvider;
}
public GxpClosure render() {
try {
BbcFeed bbcWorldNews = worldNewsFeedProvider.get();
BbcFeed bbcSports = sportsFeedProvider.get();
return NewsWidgetBody.getGxpClosure(bbcWorldNews, bbcSports);
} catch (FeedUnavailableException e) {
return UnavailableWidgetBody.getGxpClosure();
}
}
}
スコーピングに関するノート
スコープもプロバイダに関して同じように動作する。 get()が呼び出されるときには、返されたオブジェクトは適切にスコープされる。 例外も同じくスコープされる。 例えば、worldNewsFeedProvider.get()が例外を投げると、その同じ例外がスコープ内のすべての呼び出し側に返される。
