@ManagedBean対@Controller
まず、Bean を管理するフレームワークを1 つ選択する必要があります。Bean を管理するには、JSF または Spring (または CDI) のいずれかを選択する必要があります。以下は機能しますが、根本的に間違っています。
@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}
まったく同じマネージド Bean クラスの2 つの完全に別個のインスタンスが作成されます。1 つは JSF によって管理され、もう 1 つは Spring によって管理されます。として参照する場合、実際に EL で使用されるものは明確ではありません#{someBean}。SpringBeanFacesELResolverに登録している場合faces-config.xmlは、JSF 管理のものではなく、Spring 管理のものになります。それがない場合は、JSF 管理のものになります。
@RequestScopedまた、 、@ViewScoped、@SessionScopedまたは@ApplicationScopedfrom packageなどの JSF マネージド Bean 固有のスコープを宣言すると、javax.faces.*によってのみ認識および使用され@ManagedBeanます。@Controller独自の@Scope注釈が必要なため、理解されません。存在しない場合、これはデフォルトでシングルトン (アプリケーション スコープ) になります。
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
@Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
を介して上記の Bean を参照する#{someBean}と、JSF 管理のビュー スコープ Bean ではなく、Spring 管理のアプリケーション スコープ Bean が返されます。
@ManagedProperty対@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に従ってSpringBeanFacesELResolver登録した場合は、faces-config.xml
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
したがって、Spring マネージド Bean を 経由で EL で#{springBeanName}参照できます@ManagedProperty。基本的には、指定された EL 式の評価結果を設定するため、それらを参照することもできます。逆に、 を介して JSF マネージド Bean を注入すること@Autowiredは、まったくサポートされていません。ただし@Autowired、Bean を から拡張する場合は、JSF マネージド Bean で を使用できますSpringBeanAutowiringSupport。これにより、コンストラクターの呼び出し中に 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 の拡張を許可しない場合は、以下のように、いつでも JSF マネージド Bean インスタンスを Spring autowirable コンテキストに手動で登録できます。トリックについては、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対@Scope
Spring@Scopeでは、JSF スコープのサポートが制限されています。JSF の に相当するものはありません@ViewScoped。基本的には、独自のスコープを自作するか、上記のように Spring autowirable コンテキストで JSF マネージド Bean インスタンスを手動で登録することに固執します。
@FlowScoped一方、Spring WebFlow は、新しいアノテーションを介して JSF 2.2 に引き継がれました。したがって、すでに JSF 2.2 を使用している場合、フロー スコープのみが必要な場合は、必ずしも Spring WebFlow を使用する必要はありません。
CDI - すべてを統一しようとしています
Java EE 6 以降、CDI は Spring DI の標準的な代替手段として提供されています。これにはそれぞれ@Namedと の@Inject注釈があり、独自のスコープ セットもあります。Spring を使用していないため、Spring とどのように相互作用するかはわかりませんが、@Inject内で動作し@ManagedBean、@ManagedProperty内でBean@ManagedBeanを参照できます。@Named一方、Bean@ManagedProperty内では機能しません。@Named
CDI の目的は、すべての異なる Bean 管理フレームワークを 1 つの仕様/インターフェースに統合することです。Spring は完全な CDI 実装であった可能性がありますが、部分的にのみ実装することを選択しました (JSR-330 のみjavax.inject.*がサポートされ、JSR-299 はサポートされてjavax.enterprise.context.*いません)。Spring は CDI をサポートしますか?も参照してください。そしてこのチュートリアル。
@ManagedBeanJSF は、将来のバージョンで Bean 管理と非推奨およびフレンドのために CDI に移行する予定です。
@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.
}
}
以下も参照してください。