使用 CDI。
根据 JSF 2.3,@ManagedBean
不推荐使用。另见规范问题 1417。这意味着不再有选择的@ManagedBean
理由@Named
。这首先在 Mojarra 2.3.0 beta 版本 m06 中实现。
历史
核心区别在于,@ManagedBean
由 JSF 框架管理,并且只能通过@ManagedProperty
另一个 JSF 托管 bean 使用。@Named
由应用程序服务器(容器)通过 CDI 框架管理,并且@Inject
可用于任何类型的容器管理工件,如@WebListener
, @WebFilter
, @WebServlet
, @Path
,@Stateless
等,甚至是 JSF @ManagedBean
。另一方面,在容器管理的工件或任何其他容器管理的工件内@ManagedProperty
不起作用。它真的只在里面工作。@Named
@ManagedBean
另一个区别是 CDI 实际上在每个请求/线程的基础上注入委托给目标范围内的当前实例的代理(就像注入 EJB 的方式一样)。这种机制允许将一个范围更窄的 bean 注入一个范围更广的 bean 中,这在 JSF 中是不可能的@ManagedProperty
。JSF 通过调用 setter 直接在此处“注入”物理实例(这也是需要 setter 的原因,而@Inject
.
虽然不是直接的劣势——还有其他方式——但范围@ManagedBean
只是有限的。从另一个角度来看,如果您不想为 暴露“太多” @Inject
,您也可以只保留托管 bean @ManagedBean
。这就像protected
对public
。但这还不算。
至少,在 JSF 2.0/2.1 中,通过 CDI 管理 JSF 支持 bean 的主要缺点是没有与@ViewScoped
. @ConversationScoped
接近了,但仍然需要手动启动和停止,并且它会在cid
结果 URL 上附加一个丑陋的请求参数。MyFaces CODI 通过完全透明地将 JSF 桥javax.faces.bean.ViewScoped
接到 CDI 使您可以更轻松地进行操作@Named @ViewScoped
,但是这会在结果 URL 上附加一个丑陋的windowId
请求参数,同样适用于普通的页面到页面导航。OmniFaces用真正的 CDI 解决了这一切,@ViewScoped
它真正将 bean 的范围与 JSF 视图状态联系起来,而不是与任意请求参数联系起来。
JSF 2.2(在这个问题/答案后 3 年发布)提供了一个新的完全兼容 CDI@ViewScoped
的注释,以javax.faces.view.ViewScoped
. JSF 2.2 甚至附带了一个@FlowScoped
没有@ManagedBean
等价物的 CDI-only,从而将 JSF 用户推向 CDI。根据 Java EE 8的预期,它@ManagedBean
和朋友将被弃用。如果您目前仍在使用@ManagedBean
,因此强烈建议切换到 CDI 为将来的升级路径做好准备。CDI 在与 Java EE Web Profile 兼容的容器中很容易获得,例如 WildFly、TomEE 和 GlassFish。对于 Tomcat,您必须单独安装它,就像您已经为 JSF 所做的那样。另请参阅如何在 Tomcat 中安装 CDI?