web-dev-qa-db-ja.com

Spring JSF統合:JSFマネージドBeanにSpringコンポーネント/サービスを注入する方法

マネージドBeanはコントローラのように機能することを理解しています。これは、ビューレイヤーをモデルに「リンク」するだけだからです。

BeanをマネージドBeanとして使用するには、_@ManagedBean_ annotationを宣言する必要があります。これを行うと、JSFとBeanを直接通信できます。

この管理対象Beanに(Springの)コンポーネントを注入する場合、2つの方法があります。

  1. ManagedBeanのプロパティ(「BasicDAO dao」など)を選択し、プロパティの上で@ManagedProperty(#{"basicDAO"})を宣言します。そうすることで、ManagedBeanでSpringからBean _"basicDAO"_を注入しています。

  2. ManagedBeanクラスで@Controllerを宣言すると、_@ManagedBean_および_@Controller_注釈がすべて一緒になります。そして、プロパティ_"BasicDAO dao"_では、Springの_@Autowired_を使用する必要があります。

私の理解は正しいですか?

39

JSF BeanをSpringBeanAutowiringSupportから拡張するだけで、JSF管理BeanでSpring管理Beanを使用する別の方法があり、Springは依存性注入を処理します。

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.

    // springBeanName is now available.
}
8
tylerdurden

@ManagedBean vs @Controller

まず、Beanを管理するフレームワークoneを選択する必要があります。 Beanを管理するには、JSFまたはSpring(またはCDI)を選択する必要があります。以下は機能しますが、根本的に間違っています。

@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}

最終的には、two2つの(-===-)完全に分離されたインスタンスになります。1つはJSFによって管理され、もう1つはSpringによって管理されます。 #{someBean}として参照するときにELで使用される実際が直接明確ではありません。 SpringBeanFacesELResolverfaces-config.xmlに登録されている場合、JSF管理のものではなく、Spring管理のものになります。持っていない場合は、JSFが管理するものになります。

また、@RequestScoped@ViewScoped@SessionScoped、または@ApplicationScopedからjavax.faces.*パッケージなど、JSFマネージドBean固有のスコープを宣言すると、認識されるだけです。 @ManagedBeanで使用されます。 @Controllerは、独自の@Scopeアノテーションを予期しているため、理解されません。存在しない場合、これはデフォルトでシングルトン(アプリケーションスコープ)になります。

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
@Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}

#{someBean}を介して上記のBeanを参照すると、JSF管理のビュースコープBeanではなく、Spring管理のアプリケーションスコープBeanが返されます。


@ManagedProperty vs @Autowired

JSF固有の@ManagedPropertyは、JSF管理のBeanでのみ、つまり@ManagedBeanを使用している場合にのみ機能します。 Spring固有の@Autowiredは、Spring管理のBeanでのみ、つまり@Controllerを使用している場合にのみ機能します。以下のアプローチは同等またはそれ以下であり、混在させることはできません。

@ManagedBean // JSF-managed.
@RequestScoped // JSF-managed scope.
public class GoodBean {

    @ManagedProperty("#{springBeanName}")
    private SpringBeanClass springBeanName; // Setter required.
}
@Component // Spring-managed.
@Scope("request") // Spring-managed scope.
public class GoodBean {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.
}

javadoc に従ってfaces-config.xmlSpringBeanFacesELResolver を登録している場合、

<application>
    ...
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>

したがって、#{springBeanName}を介してELでSpringマネージドBeanを参照できます。また、特定のEL式の評価結果を基本的に設定するので、@ManagedPropertyでも参照できます。反対の方法で、@Autowiredを介してJSFマネージドBeanを注入することは、サポートされていません。ただし、 SpringBeanAutowiringSupport からBeanを拡張する場合、JSF管理Beanで@Autowiredを使用できます。これにより、コンストラクターの呼び出し中にJSFマネージドBeanインスタンスがSpring autowirableコンテキストに自動的に登録されます。つまり、@Autowired以降のすべてで@PostConstructが使用可能になります。

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport implements Serializable {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.

    @PostConstruct
    private void init() {
        // springBeanName is now available.
    }
}

または、アーキテクチャが別の基本クラスからのBeanの拡張を許可していない場合は、次のように、Spring autowirableコンテキストでJSF管理Beanインスタンスをいつでも手動で登録できます。 JSF 2とSpring 3(またはSpring 4)をうまく統合する方法 も参照してください。

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.

    @PostConstruct
    private void init() {
        FacesContextUtils
            .getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
            .getAutowireCapableBeanFactory().autowireBean(this);

        // springBeanName is now available.
    }
}

@XxxScoped vs @Scope

Springの@Scopeでは、JSFスコープのサポートが制限されています。 JSFの@ViewScopedに相当するものはありません。基本的に、独自のスコープを自作するか、上記のようにJSF管理BeanインスタンスをSpringの自動書き込み可能なコンテキストに手動で登録します。

そして、反対側から、Spring WebFlowは新しい@FlowScopedアノテーションを介してJSF 2.2に引き継がれました。したがって、JSF 2.2をすでに使用している場合、フロースコープのみが必要な場合は必ずしもSpring WebFlowを使用する必要はありません。


CDI-すべてを統一しよう

Java EE 6)から、CDIはSpring DIの標準代替として提供されます。これにはそれぞれ@Namedおよび@Inject注釈があり、独自のスコープセットもあります。 'Springを使用していないため、Springとどのように相互作用するかはわかりませんが、@Inject@ManagedBean内で機能し、@ManagedProperty@ManagedBean内で機能し、@Named Bean。一方、@ManagedProperty@Named Bean内では機能しません。

CDIの目的は、すべての異なるBean管理フレームワークを1つの仕様/インターフェースのみに統合することです。 Springは完全なCDI実装でしたが、部分的にのみ実装することを選択しました(JSR-330 javax.inject.*のみがサポートされますが、JSR-299 javax.enterprise.context.*はサポートされません)。 SpringはCDIをサポートしますか? および このチュートリアル も参照してください。

JSFは、Bean管理のためにCDIに移行し、将来のバージョンで@ManagedBeanおよび友人を非推奨にします。

@Named // CDI-managed.
@ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {

    @Inject
    private SpringBeanClass springBeanName; // No setter required.

    @PostConstruct
    private void init() {
        // springBeanName is now available.
    }
}

こちらもご覧ください:

77
BalusC

これを行う簡単な方法は、XMLを使用することです。すでに作成されたjsf管理対象Beanで@Componentを使用しましたが、管理対象Beanがfaces-config.xmlにすでに存在するため、@Autowiredは機能しませんでした。マネージドBeanの定義とそのマネージドプロパティをxmlファイルに保持することが必須である場合は、マネージドBeanタグ内の別のマネージドプロパティとしてSpring Beanを追加することをお勧めします。ここで、Spring Beanはspring-config.xmlで定義されています(別の場所に自動配線できます)。参照してください https://stackoverflow.com/a/19904591/5620851

私が編集しました。アノテーション@Managedと@Componentを使用するか、両方のxmlを使用して実装することをお勧めします。

1
hi.nitish