支持豆(@ManagedBean)或CDI豆(@Named)?

我刚刚开始阅读通过核心JavaServer Faces,第三版。 他们说这个(重点是我的):

对于可以在JSF页面中使用的bean,有两个单独的机制,即CDI bean和JSF managed beans,这是一个历史性的意外。 我们build议您使用CDI bean,除非您的应用程序必须使用纯粹的servlet运行程序(如Tomcat)。

为什么? 他们没有提供任何理由。 我在GlassFish 3上运行的原型应用程序中的所有bean都使用了@ManagedBean ,而且我还没有真正注意到这个问题。 我不特别介意从@ManagedBean迁移到@Named ,但是我想知道为什么我应该打扰

CDI比普通的JSF更受欢迎,因为CDI允许JavaEE范围内的dependency injection。 你也可以注入POJO并让它们被pipe理。 使用JSF,你只能注入CDI的一部分。

使用CDI。

根据JSF 2.3,@ @ManagedBean已被弃用 。 另请参阅规格问题1417 。 这意味着没有理由select@ManagedBean不是@Named 。 这是在Mojarra 2.3.0 beta版本m06中首次实现的。

在这里输入图像描述


历史

核心的区别在于,@ @ManagedBean由JSF框架pipe理,只能通过@ManagedProperty提供给另一个JSFpipe理的bean。 @Named由应用程序服务器(容器)通过CDI框架进行pipe理,并通过@Inject可用于任何种类的容器pipe理的工件,如@WebListener@Stateless @WebListener@Stateless @WebListener@Stateless @WebListener@Stateless等,甚至JSF @ManagedBean 。 另一方面,@ @ManagedProperty@Named或任何其他容器pipe理的工件中不起作用。 它真的只在@ManagedBean

另一个区别是,CDI实际上是在每个请求/线程的基础上(比如如何注入EJB),在目标范围内注入委托给当前实例的代理。 这种机制允许在更广泛的bean中注入更窄范围的bean,这对于JSF @ManagedProperty是不可能的。 JSF通过调用setter直接在这里注入物理实例(这也正是为什么需要setter,而@Inject不需要)。

虽然不是直接的缺点 – 还有其他的方法 – @ManagedBean的范围是有限的。 从另一个angular度来看,如果你不想为@Inject公开“太多”,你也可以保留你的托pipebean @ManagedBean 。 这就像protectedpublic 。 但是这不算真正的数字。

至less,在JSF 2.0 / 2.1中,CDIpipe理JSF支持bean的主要缺点是没有CDI相当于@ViewScoped@ConversationScoped接近,但仍需要手动启动和停止,并将丑陋的cid请求参数附加到结果URL。 通过将JSF的javax.faces.bean.ViewScoped完全透明地桥接到CDI,MyFaces CODI使得它更容易,因此您可以执行@Named @ViewScoped ,但是它会在结果URL上附加一个丑陋的windowId请求参数,也会在普通的vanilla页面间导航。 OmniFaces通过一个真正的CDI @ViewScoped解决了这个问题,它真正将bean的范围连接到JSF视图状态,而不是任意的请求参数。

JSF 2.2(在这个问题/答案之后的3年发布)提供了一个新的完全兼容CDI的@ViewScoped注解, javax.faces.view.ViewScoped 。 JSF 2.2甚至还带有一个只@FlowScoped CDI的@FlowScoped ,它没有一个@ManagedBean等价物,从而把JSF用户推向了CDI。 期望的是@ManagedBean和朋友将被弃用,按照Java EE 8。如果您目前仍在使用@ManagedBean ,那么强烈build议切换到CDI以备将来的升级途径。 CDI随时可用于Java EE Web Profile兼容容器,如WildFly,TomEE和GlassFish。 对于Tomcat,您必须单独安装它,就像您已经为JSF做的一样。 另请参见如何在Tomcat中安装CDI?

使用Java EE 6和CDI,您可以select托pipe豆

  • @javax.faces.bean.ManagedBean是指JSR 314,并且是与JSF 2.0一起引入的。 主要目标是避免faces-config.xml文件中的configuration在JSF页面中使用bean。
  • @javax.annotation.ManagedBean(“myBean”)由JSR 316定义。它概括了JSFpipe理的bean,供在Java EE中使用
  • @javax.inject.Named(“myBean”)几乎与上面的一样,只是在web / WEB-INF文件夹中需要一个beans.xml文件来激活CDI。

我在GlassFish 3.0.1中使用了CDI,但为了使它工作,我不得不导入Seam 3框架(焊接)。 这工作得很好。

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

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

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

另一方面, @ViewScoped是坚持使用JSF @ManagedBean的强有力的理由 – 特别是对于任何具有重要AJAX的东西。 CDI没有这个标准的替代品。

似乎它可能有一些支持类似@ViewScoped的CDI bean的注释,但是我没有亲自玩过它。

http://seamframework.org/Seam3/FacesModule