マネージドBeanはコントローラのように機能することを理解しています。これは、ビューレイヤーをモデルに「リンク」するだけだからです。
BeanをマネージドBeanとして使用するには、_@ManagedBean
_ annotationを宣言する必要があります。これを行うと、JSFとBeanを直接通信できます。
この管理対象Beanに(Springの)コンポーネントを注入する場合、2つの方法があります。
ManagedBeanのプロパティ(「BasicDAO dao」など)を選択し、プロパティの上で@ManagedProperty(#{"basicDAO"})
を宣言します。そうすることで、ManagedBeanでSpringからBean _"basicDAO"
_を注入しています。
ManagedBeanクラスで@Controllerを宣言すると、_@ManagedBean
_および_@Controller
_注釈がすべて一緒になります。そして、プロパティ_"BasicDAO dao"
_では、Springの_@Autowired
_を使用する必要があります。
私の理解は正しいですか?
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.
}
@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で使用される実際が直接明確ではありません。 SpringBeanFacesELResolver
がfaces-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.xml
に SpringBeanFacesELResolver
を登録している場合、
<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を使用する必要はありません。
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.
}
}
これを行う簡単な方法は、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を使用して実装することをお勧めします。