1

依存性注入ツールを使用しない Web アプリケーションの隣にある Google Guice を使用してコンポーネントを作成しています。

コンポーネントの Guice モジュールには、変更されないいくつかの「固定」バインディングと、Web アプリケーションからのすべてのリクエストで変更されるため動的なバインディングがいくつかあります。

私がこれを解決した簡単な (そして悪い) 方法は、Web アプリケーションが初めてコンポーネントに何かを要求するたびに、コンポーネントが新しい Guice モジュールを構築し、インスタンスを作成して Web アプリに返すことです。

public static X init(@NotNull final Foo perRequestObject, @NotNull final Bar perRequestObject2)
{
    final Injector injector = Guice.createInjector(new AbstractModule()
    {
        @Override
        protected void configure()
        {
            install(new NonChanging Module());
            bind(Foo.class).toInstance(perRequestObject);
            bind(Bar.class).toInstance(perRequestObject2);
        }
    });
    return return injector.getInstance(X.class);
}

リクエストごとにインジェクターを構築するのはコストがかかるため、これは悪いアプローチだと思います。私が欲しいのは、実行時にオーバーライドできる作成済みのインジェクターです。私は周りにいくつかのものを見つけました:

1-動的バインディングをオーバーライドします(https://stackoverflow.com/a/531110/1587864に回答してください)。これにはまだ新しいインジェクターを作成する必要があるため、同じ問題が発生します。

2- Injector に既にバインドされており、Web アプリケーションから取得され、要求ごとの「動的」プロパティにアクセスできるある種の Factory を実装します。

2番目のものを実装する方法がわかりません.この概念はGuiceに存在しますか?

ありがとう

4

1 に答える 1

3

As the comments say, the full proper solution is a Scope. Assuming you've copied the implementation of SimpleScope from this article into your project, then here's what I'd do in your component. As you do above, I assume Foo and Bar are the objects you need created on a per-request basis, and X is the class of the thing you ultimately need Guice to create. I assume further that X has on it a method called doTheActualRequestLogic that is the method you wish to call to ultimately return back to the servlet:

public class MyWebComponent
{
  private final Provider<X> theGuiceCreatedObject;
  private final SimpleScope perRequestScope;

  public MyWebComponent() {
    perRequestScope = new SimpleScope();
    Injector injector = Guice.createInjector(new AbstractModule()
    {
        @Override
        protected void configure()
        {
            install(new NonChangingModule());
            bind(Foo.class).toProvider(SimpleScope.seededKeyProvider())
                .in(perRequestScope);
            bind(Bar.class).toProvider(SimpleScope.seededKeyProvider())
                .in(perRequestScope);
        }
    });
    theGuiceCreatedObject = injector.getProvider(X.class);
  }

  // I assume methods called makeFoo and makeBar that can make
  // a Foo or Bar for a request

  // called by the web service to say "handle this request"
  public RequestResult handleRequest(DataToMakeFooAndBarWith requestData) {
    try {
      perRequestScope.enter();
      perRequestScope.seed(Foo.class, makeFoo(requestData));
      perRequestScope.seed(Bar.class, makeBar(requestData));
      return theGuiceCreatedObject.get().doTheActualRequestLogic(requestData);
    } finally {
      perRequestScope.exit();
    }
  }
}
于 2014-07-12T19:54:13.680 に答える