@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
または@ApplicationScoped
from 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 をサポートしますか?も参照してください。そしてこのチュートリアル。
@ManagedBean
JSF は、将来のバージョンで 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.
}
}
以下も参照してください。