使用CDI。
根据JSF 2.3的规定,@ManagedBean
已被弃用。请参见规范问题1417。这意味着没有理由再选择@ManagedBean
而不是@Named
。这在Mojarra 2.3.0 beta版本m06中首次实现。
![enter image description here](https://istack.dev59.com/YdG3r.webp)
自从Faces 4.0版本,根据规范
issue 1547,
@ManagedBean
已被
移除。
历史
核心区别在于,@ManagedBean
由JSF框架管理,并且只能通过 @ManagedProperty
提供给另一个JSF托管的bean。@Named
由应用服务器(容器)通过CDI框架管理,并且可以通过 @Inject
提供给任何类型的容器管理的构件,如 @WebListener
、@WebFilter
、@WebServlet
、@Path
、@Stateless
等,甚至是JSF中的 @ManagedBean
。从另一方面来看,在 @Named
或任何其他容器管理的构件中,@ManagedProperty
不起作用。它实际上只在 @ManagedBean
中起作用。
另一个区别在于,CDI实际上会注入代理对象,以每个请求/线程为基础委派到目标范围中的当前实例(就像EJB的注入方式一样)。这种机制允许将较窄范围的bean注入到较宽范围的bean中,而使用JSF的
@ManagedProperty
则不可能实现。JSF在此处直接通过调用setter方法“注入”物理实例(这也正是为什么需要setter方法,而使用
@Inject
则不需要setter方法的原因)。
虽然不直接具有劣势——还有其他方法——但
@ManagedBean
的范围是有限的。从另一个角度来看,如果您不想为
@Inject
公开“太多”,您也可以将托管bean保持为
@ManagedBean
。这就像
protected
与
public
一样。但那并不重要。
至少在JSF 2.0/2.1中,通过CDI管理JSF backing bean的主要缺点是没有
@ViewScoped
的CDI等价物。
@ConversationScoped
接近,但仍需要手动启动和停止,并且会向outcome URL附加一个丑陋的
cid
请求参数。 MyFaces CODI通过完全透明地桥接JSF的
javax.faces.bean.ViewScoped
到CDI,使其更容易实现,因此您只需执行
@Named @ViewScoped
即可,但是这会向outcome URL添加一个丑陋的
windowId
请求参数,即使是普通的页面导航也是如此。
OmniFaces通过真正将bean的范围绑定到JSF视图状态而不是任意请求参数来解决所有这些问题,提供了真正的CDI
@ViewScoped
。
JSF 2.2(在此问题/答案发布3年后发布)提供了一个全新的完全CDI兼容的@ViewScoped
注释,作为javax.faces.view.ViewScoped
的一种变体。JSF 2.2甚至还带有仅限于CDI的@FlowScoped
,它没有@ManagedBean
等效项,从而推动JSF用户向CDI。预期@ManagedBean
和其它相关内容将被Java EE 8弃用。因此,如果您目前仍在使用@ManagedBean
,强烈建议切换到CDI以准备未来的升级路径。CDI已经在Java EE Web Profile兼容的容器中可用,例如WildFly、TomEE和GlassFish。对于Tomcat,您必须单独安装它,就像您已经为JSF做的那样。另请参见如何在Tomcat中安装CDI?