支持bean(@ManagedBean)或CDI Beans(@Named)?

时间:2010-12-03 16:05:11

标签: jsf java-ee jsf-2 cdi

我刚刚开始阅读Core JavaServer Faces, 3rd Ed.并且他们这样说(强调我的):

  

这是一个历史事故,有两个独立的机制,CDI bean   和JSF托管bean,用于可以在JSF页面中使用的bean。 我们建议   您使用CDI bean ,除非您的应用程序必须在普通的servlet上工作   像Tomcat这样的跑步者。

为什么呢?他们不提供任何理由。我一直在使用@ManagedBean用于在GlassFish 3上运行的原型应用程序中的所有bean,我还没有发现任何问题。我并不特别介意从@ManagedBean迁移到@Named,但我想知道为什么我应该打扰

5 个答案:

答案 0 :(得分:167)

使用CDI。

根据JSF 2.3,@ManagedBean 已弃用。另见spec issue 1417。这意味着没有理由选择@ManagedBean而不是@Named。这首先在Mojarra 2.3.0 beta版m06中实现。

enter image description here


历史

核心区别在于,@ManagedBean由JSF框架管理,并且只能通过@ManagedProperty可用于其他JSF托管bean。 @Named由应用程序服务器(容器)通过CDI框架管理,并通过@Inject可用于任何类型的容器管理工件,如@WebListener@WebFilter,{{1 }},@WebServlet@Path等,甚至是JSF @Stateless。另一方面,@ManagedBean@ManagedProperty或任何其他容器管理工件内工作。它实际上只在@Named内部。

另一个不同之处在于,CDI实际上会在每个请求/线程的基础上注入委托给目标作用域中当前实例的代理(就像EJB的注入方式一样)。这种机制允许在更广泛范围的bean中注入范围更窄的bean,这对于JSF @ManagedBean是不可能的。 JSF直接通过调用setter来“注入”物理实例(这也正是为什么需要setter的原因,而@ManagedProperty需要 )。

虽然不是直接的劣势 - 还有其他方式 - @Inject的范围仅限于此。从另一个角度来看,如果您不想为@ManagedBean公开“太多”,您也可以保留托管bean @Inject。这就像@ManagedBeanprotected一样。但这并不重要。

至少在JSF 2.0 / 2.1中,CDI管理JSF支持bean的主要缺点是没有CDI等价于public@ViewScoped接近,但仍需要手动启动和停止,并在结果网址中附加一个丑陋的@ConversationScoped请求参数。通过完全透明地将JSF的cid桥接到CDI,MyFaces CODI可以更轻松地完成javax.faces.bean.ViewScoped,但是这会在结果URL上添加一个丑陋的@Named @ViewScoped请求参数,同样在普通的页面上 - 页面导航。 OmniFaces使用真正的CDI @ViewScoped解决了这一问题,它真正将bean的范围与JSF视图状态联系起来,而不是与任意请求参数联系起来。

JSF 2.2(在此问题/答案之后3年发布)提供了一个全新的CDI兼容windowId注释,其内容为@ViewScoped。 JSF 2.2甚至还附带了一个CDI-only javax.faces.view.ViewScoped,它没有@FlowScoped等价物,因此将JSF用户推向了CDI。期望@ManagedBean和朋友将根据Java EE 8弃用。如果您当前仍在使用@ManagedBean,因此强烈建议切换到CDI以备将来的升级路径使用。 CDI可以在Java EE Web Profile兼容容器中使用,例如WildFly,TomEE和GlassFish。对于Tomcat,您必须单独安装它,就像您为JSF所做的那样。另请参阅How to install CDI in Tomcat?

答案 1 :(得分:61)

CDI优于普通JSF,因为CDI允许JavaEE范围的依赖注入。您还可以注入POJO并管理它们。使用JSF,您只能使用CDI注入一部分内容。

答案 2 :(得分:13)

使用Java EE 6和CDI,您可以使用不同的Managed Beans选项

  • @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。

答案 3 :(得分:2)

我在GlassFish 3.0.1中使用CDI,但要使其工作,我必须导入Seam 3框架(Weld)。这非常有效。

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

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

答案 4 :(得分:0)

转向CDI的一个很好的理由:您可以在JSF托管bean和REST服务(即Jersey / JAX-RS)中使用公共会话范围的资源(例如用户配置文件)@Inject

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

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

http://seamframework.org/Seam3/FacesModule