111

我刚刚开始阅读Core JavaServer Faces,第 3 版。他们这样说(强调我的):

对于可以在 JSF 页面中使用的 bean,有两种独立的机制,CDI bean 和 JSF 管理的 bean,这是一个历史性的意外。我们建议您使用 CDI bean,除非您的应用程序必须在普通的 servlet 运行程序(如 Tomcat)上运行。

为什么?他们没有提供任何理由。我一直在使用@ManagedBeanGlassFish 3 上运行的原型应用程序中的所有 bean,但我并没有真正注意到任何问题。我不特别介意从@ManagedBeanto迁移@Named,但我想知道我为什么要打扰

4

5 回答 5

177

使用 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。这就像protectedpublic。但这还不算。

至少,在 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?

于 2010-12-03T16:36:12.623 回答
65

CDI 优于普通 JSF,因为 CDI 允许 JavaEE 范围的依赖注入。您还可以注入 POJO 并让它们进行管理。使用 JSF,您只能注入使用 CDI 所能实现的功能的一个子集。

于 2010-12-03T16:36:45.717 回答
17

使用 Java EE 6 和 CDI,您有不同的托管 Bean 选项

  • @javax.faces.bean.ManagedBean是指 JSR 314 并在 JSF 2.0 中引入。主要目标是避免在 faces-config.xml 文件中进行配置以使用 JSF 页面中的 bean。
  • @javax.annotation.ManagedBean(“myBean”)由 JSR 316 定义。它概括了 JSF 托管 bean,以便在 Java EE 的其他地方使用
  • @javax.inject.Named(“myBean”)与上面的几乎相同,只是您需要 web/WEB-INF 文件夹中的 beans.xml 文件来激活 CDI。
于 2010-12-09T10:55:49.197 回答
2

我在 GlassFish 3.0.1 中使用 CDI,但为了让它工作,我必须导入 Seam 3 框架 (Weld)。那工作得很好。

在 GlassFish 3.1 中,CDI 停止工作,Seam Weld 停止使用它。我为此打开了一个错误,但还没有看到它修复。我不得不将我的所有代码都转换为使用 javax.faces.* 注释,但我计划在它们开始工作后回到 CDI。

我同意您应该使用 CDI,但我还没有看到解决的一个问题是如何处理 @ViewScoped 注释。我有很多依赖于它的代码。如果您不使用@ManagedBean,则尚不清楚@ViewScoped 是否有效。如果有人能澄清这一点,我将不胜感激。

于 2010-12-25T02:00:46.110 回答
-1

迁移到 CDI 的一个很好的理由是:您可以@Inject在 JSF 托管 bean 和 REST 服务(即 Jersey/JAX-RS)中拥有一个通用的会话范围资源(例如用户配置文件)。

另一方面,@ViewScoped这是坚持使用 JSF 的一个令人信服的理由@ManagedBean——尤其是对于任何具有重要 AJAX 的东西。在 CDI 中没有标准的替代品。

似乎它可能@ViewScoped对 CDI bean 的 -like 注释有一些支持,但我个人没有玩过它。

http://seamframework.org/Seam3/FacesModule

于 2011-08-01T23:46:04.070 回答