支持 bean (@ManagedBean)还是 CDI Bean (@Named) ?

我刚开始通读 核心 JavaServer Faces,第三版。,他们说(强调我的) :

存在两个独立的机制 CDI bean 是一个历史偶然 和 JSF 托管 bean,用于可以在 JSF 页面中使用的 bean that you use CDI beans unless your application must work on a plain servlet 像雄猫这样的赛跑运动员。

为什么?他们没有提供 任何证明。我一直在运行在 GlassFish 3上的原型应用程序中的所有 bean 中使用 @ManagedBean,并且我没有真正注意到这方面的任何问题。我不特别介意从 @ManagedBean迁移到 @Named,但是我想知道 我为什么要费心

78405 次浏览

使用 CDI。

根据 JSF 2.3,@ManagedBean不赞成。参见 第1417期。这意味着再也没有理由选择 @ManagedBean而不是 @Named了。这是首次在 Mojarra 2.3.0 beta 版本 m06中实现。

enter image description here

自从面对4.0以来,@ManagedBean一直是按照规范 第1547期被移除了


History

核心区别在于,@ManagedProperty3是由 JSF 框架管理的,并且只能通过 @ManagedProperty4对另一个 JSF 管理的 bean 可用。@ManagedProperty5通过 CDI 框架由应用服务器(容器)管理,并且通过 @ManagedProperty6可用于任何类型的容器管理构件,如 @WebListener@WebFilter@WebServlet@Path@Stateless等,甚至 JSF @ManagedBean。从另一方面来看,@ManagedProperty@Named或任何其他容器管理的构件内进行 @ManagedProperty7工作。它只能在 @ManagedBean内部使用。

另一个不同之处在于,CDI 实际上是根据每个请求/线程(就像 EJB 是如何被注入的一样)在目标作用域中注入委托给当前实例的代理。这种机制允许在范围更广的 bean 中注入范围更窄的 bean,而这在 JSF@ManagedProperty中是不可能的。JSF 在这里通过调用 setter 直接“注入”物理实例(这也正是为什么需要 setter,而 @Inject需要 没有)。

尽管 @ManagedBean并非直接的劣势(还有其它方式) ,但它的规模确实有限。从另一个角度来看,如果不想为 @Inject暴露“太多”,也可以只保留托管 bean @ManagedBean。就像 protectedpublic。但那不算。

At least, in JSF 2.0/2.1, the major disadvantage of managing JSF backing beans by CDI is that there's no CDI equivalent of @ViewScoped. The @ConversationScoped comes close, but still requires manually starting and stopping and it appends an ugly cid request parameter to outcome URLs. MyFaces CODI makes it easier by fully transparently bridging JSF's javax.faces.bean.ViewScoped to CDI so you can just do @Named @ViewScoped, however that appends an ugly windowId request parameter to outcome URLs, also on plain vanilla page-to-page navigation. OmniFaces solves this all with a true CDI @ViewScoped which really ties the bean's scope to JSF view state instead of to an arbitrary request parameter.

JSF 2.2(在这个问题/答案出现3年后发布)提供了一个新的完全兼容 CDI 的 @ViewScoped注释,类似于 javax.faces.view.ViewScoped。JSF 2.2甚至还附带了一个只有 CDI 的 @FlowScoped,它没有相应的 @ManagedBean,因此将 JSF 用户推向了 CDI。预计 @ManagedBean和朋友将按照 JavaEE8被弃用。如果您目前仍在使用 @ManagedBean,因此强烈建议切换到 CDI,以便为将来的升级路径做好准备。CDI 在 JavaEEWebProfile 兼容的容器(如 WildFly、 TomEE 和 GlassFish)中很容易获得。对于 Tomcat,您必须单独安装它,正如您已经对 JSF 所做的那样。参见 如何在 Tomcat 中安装 CDI?

相对于普通的 JSF,CDI 更受欢迎,因为它支持 JavaEE 范围的依赖注入。还可以注入 POJO 并对其进行管理。使用 JSF 时,您只能注入 CDI 所能注入内容的一个子集。

With Java EE 6 and CDI you have different option for Managed Beans

  • @javax.faces.bean.ManagedBean是参考 JSR 314的,是随 JSF 2.0引入的。主要目标是避免 faces-config.xml 文件中的配置在 JSF 页面中使用 bean。
  • @javax.annotation.ManagedBean(“myBean”)是由 JSR316定义的,它通用化了 JSF 托管 bean,以便在 JavaEE 的其他地方使用
  • @javax.inject.Named(“myBean”)与上面那个几乎相同,只是需要 web/WEB-INF 文件夹中的 beans.xml 文件来激活 CDI。

我在 GlassFish 3.0.1中使用 CDI,但是为了让它工作,我必须导入 Seam 3框架(Weld)。效果不错。

在 GlassFish 3.1中,CDI 停止工作,Seam Weld 也停止使用它。我打开了一个 窃听器,但还没有看到它修复。我必须将所有代码转换为使用 javax.faces。* 注释,但我计划回到 CDI 一旦他们得到它的工作。

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

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

On the other hand, @ViewScoped is a compelling reason to stick with JSF @ManagedBean - especially for anything with significant AJAX. There is no standard replacement for this in CDI.

它似乎对 CDI bean 的类 @ViewScoped注释有一些支持,但我个人还没有使用过它。

Http://seamframework.org/seam3/facesmodule