Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment

Locked History Actions

guice/Manual/Extensions/ThrowingProviders

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> { }

WordlNewsFeedProviderSportsFeedProviderの実装を作成し、それらをモジュール内にて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()が例外を投げると、その同じ例外がスコープ内のすべての呼び出し側に返される。