我刚刚开始阅读Core JavaServer Faces, 3rd Ed.并且他们这样说(强调我的):
这是一个历史事故,有两个独立的机制,CDI bean 和JSF托管bean,用于可以在JSF页面中使用的bean。 我们建议 您使用CDI bean ,除非您的应用程序必须在普通的servlet上工作 像Tomcat这样的跑步者。
为什么呢?他们不提供任何理由。我一直在使用@ManagedBean
用于在GlassFish 3上运行的原型应用程序中的所有bean,我还没有发现任何问题。我并不特别介意从@ManagedBean
迁移到@Named
,但我想知道为什么我应该打扰。
答案 0 :(得分:167)
根据JSF 2.3,@ManagedBean
已弃用。另见spec issue 1417。这意味着没有理由选择@ManagedBean
而不是@Named
。这首先在Mojarra 2.3.0 beta版m06中实现。
核心区别在于,@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
。这就像@ManagedBean
与protected
一样。但这并不重要。
至少在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的注释一样,但我个人没有玩过它。