2

Guice を JSF 1.2 (Sun RI) アプリケーションに統合しようとしています。マネージド Bean に対して次のことを実行できるようにしたいと考えています。

  1. Guice@Injectアノテーションを使用して依存関係を注入してから、
  2. @PostConstructアノテーションを使用して初期化を実行する

私の問題は、アノテーションが処理さ@PostConstructれる前にメソッドが常に呼び出されることです。@Injectこの問題の解決策を知っている人はいますか?

管理対象 Bean:

public final class Foo {

    @Inject private BazService bazService;
    private Baz baz;

    @PostConstruct
    public void init() {
        bar = bazService.loadBaz();
    }

    public void setBazService(BazService bazService) {
        this.bazService = bazService;
    }
}

マネージド Bean 宣言:

<managed-bean>
  <managed-bean-name>foo</managed-bean-name>
  <managed-bean-class>bean.Foo</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
  <managed-property>
    <property-name>id</property-name>
    <value>#{param.id}</value>
  </managed-property>
</managed-bean>

Guice バインディング:

public final class MyGuiceModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(BazService.class).to(DummyBazService.class).in(Scopes.SINGLETON);
    }
}

私は次のことを試しました:

これが物事へのアプローチの間違った方法であると思われる場合は、他のオプションを検討させていただきます...どんな助けにも感謝します。


編集

Guice 1.0 を使用していました。Guice 2.0 にアップグレードしましたが、問題は残っています。私の問題に関連していると思われる議論をいくつか見つけました...しかし、この情報の使い方がわかりません:(

4

3 に答える 3

1

たくさん読んだ結果、@PostConstructJSF と Guice を使用する場合は避けるのが最善であるという結論に達しました。

あなたが与えた例では、注入することができますBaz

public final class Foo {

    @Inject private Baz baz;
}

Baz を Guice では作成できないが、 で作成する必要があるBazService場合は、プロバイダー メソッドを使用できます。

public final class MyGuiceModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(BazService.class).to(DummyBazService.class).in(Scopes.SINGLETON);
    }

    @Provides
    Baz provideBaz(BazService bazService) {
        return bazService.loadBaz();
    }
}
于 2009-05-21T20:47:32.307 に答える
1

残念ながら、私はあなたへの答えを持っていませんが、私はこれを言います...

オブジェクトに自分自身を注入させることはうまくいくように見えます-必ずしもスーパークラスを使用する必要はありません:

public final class Foo {

  @Inject
  private BazService bazService;
  private Baz baz;

  @PostConstruct
  public void init() {
    InjectorFinder.getInjector().injectMembers(this);
    baz = bazService.loadBaz();
  }

  public void setBazService(BazService bazService) {
    this.bazService = bazService;
  }

}

また、インジェクターへの参照を保持する理由もわかりません。そのため、ユーティリティ クラスを検討してください。

public class InjectorFinder {
  public static Injector getInjector() {
    FacesContext facesContext = FacesContext
        .getCurrentInstance();
    ExternalContext extContext = facesContext
        .getExternalContext();
    Map<String, Object> applicationMap = extContext
        .getApplicationMap();
    return (Injector) applicationMap.get(Injector.class
        .getName());
  }
}

@PostConstruct とシリアライゼーションで何か起こりますか? あまり考えたことがありませんが、セッション Bean に影響する可能性があります。


これはサウンドテクニックのようには見えません。コードを正しく読めば、オブジェクトが解決されるたびに依存関係が挿入されます。


このパッチは、私が言及した問題に悩まされていると思われます (リゾルバーが異なり、作成者が同じであることに変わりはありません)。バグはさておき、JSF の 2 つの異なる実装 (Sun と Apache) を同時に使用しようとしてもうまくいきません。


私はいくつかの Guice/JSF プロジェクトを実際に見てきました ( guicesf ; jsf-sugar ; たぶんもっとあるのでしょうか?) が、それらを試していないので、それらがあなたを助けるかどうか、あるいはそれらがどれほど安定しているかさえわかりません.

何をするにせよ、 Web Beans (概要はこちら)に目を光らせておくことをお勧めします。これは、JSF の将来の Bean 処理機能に影響を与える可能性があるためです (スタック内での Guice の位置を正しく理解していれば、それを使用してWebを実装できます)。豆 - 私があなたに勧めているわけではありません)。

于 2009-05-21T12:47:26.207 に答える
0

この答えは、この問題を解決する方法に対する良い解決策を持っているようです。具体的には、init()メソッドで@Injectアノテーションを使用することをお勧めします。これは、コンストラクターが呼び出された後に呼び出されることが保証されています。プロパティインジェクションを使用している場合は機能しない可能性があることに注意してください。

于 2011-11-01T16:13:22.147 に答える