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

Jsf 支持bean(@ManagedBean)还是CDI bean(@Named)?,jsf,jakarta-ee,jsf-2,cdi,Jsf,Jakarta Ee,Jsf 2,Cdi,我刚开始通读,他们这样说(强调我的): 有两种不同的机制,CDIBeans,这是一个历史性的意外 和JSF托管bean,用于可以在JSF页面中使用的bean我们建议 除非您的应用程序必须在普通servlet上工作,否则您必须使用CDIBeans 像Tomcat这样的跑步者 为什么??他们没有提供任何理由。我一直在使用@ManagedBean处理运行在GlassFish 3上的原型应用程序中的所有bean,但我没有注意到这方面的任何问题。我并不特别介意从@ManagedBean迁移到@Named,

我刚开始通读,他们这样说(强调我的):

有两种不同的机制,CDIBeans,这是一个历史性的意外 和JSF托管bean,用于可以在JSF页面中使用的bean我们建议
除非您的应用程序必须在普通servlet上工作,否则您必须使用CDIBeans 像Tomcat这样的跑步者

为什么??他们没有提供任何理由。我一直在使用
@ManagedBean
处理运行在GlassFish 3上的原型应用程序中的所有bean,但我没有注意到这方面的任何问题。我并不特别介意从
@ManagedBean
迁移到
@Named
,但我想知道为什么我要麻烦使用CDI。 根据JSF2.3,
@ManagedBean
已被弃用。另见。这意味着不再有理由选择
@ManagedBean
而不是
@Named
。这首先在Mojarra 2.3.0测试版m06中实现


历史 核心区别在于,它由JSF框架管理,并且只能通过另一个JSF管理的bean使用。由应用服务器(容器)通过CDI框架进行管理,并可通过任何类型的容器管理工件(如
@WebListener
@WebFilter
@WebServlet
@Path
@Stateless
)甚至JSF
@ManagedBean
)使用。从另一方面来看,
@ManagedProperty
不在名为
@的
或任何其他容器管理的工件中工作。它实际上只在
@ManagedBean
内部工作

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

虽然这不是一个直接的缺点——还有其他的方法,
@ManagedBean
的范围很有限。从另一个角度来看,如果您不想为
@Inject
公开“太多”,您也可以只保留托管bean
@ManagedBean
。这就像是
受保护
公共
的对比。但这并不重要

至少在JSF2.0/2.1中,通过CDI管理JSF支持bean的主要缺点是没有与
@ViewScoped
等价的CDI。
@ConversationScoped
很接近,但仍然需要手动启动和停止,并且它在结果URL中附加了一个丑陋的
cid
请求参数。MyFaces CODI通过将JSF的
javax.faces.bean.ViewScoped
完全透明地连接到CDI,使其变得更容易,这样您就可以只执行
@Named@ViewScoped
,但是,这会在结果URL中附加一个丑陋的
windowId
请求参数,这也是在普通的页到页导航中。使用真正的CDI解决了这一切,它将bean的作用域真正绑定到JSF视图状态,而不是任意的请求参数


JSF2.2(在这个问题/答案发布3年后发布)提供了一个全新的、完全兼容CDI的
@ViewScoped
注释,其风格是
javax.faces.view.ViewScoped
。JSF2.2甚至还附带了一个只支持CDI的
@FlowScoped
,它没有一个
@ManagedBean
等价物,从而将JSF用户推向CDI。根据JavaEE8,人们期望
@ManagedBean
和friends会被弃用。如果您当前仍在使用
@ManagedBean
,则强烈建议切换到CDI,以便为将来的升级路径做好准备。CDI在JavaEEWebProfile兼容的容器中很容易获得,如WildFly、TomEE和GlassFish。对于Tomcat,您必须单独安装它,就像对JSF一样。另请参见

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

使用JavaEE6和CDI,您可以为托管bean提供不同的选项

  • @javax.faces.bean.ManagedBean
    参考JSR314,是在JSF2.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停止工作,缝焊也停止工作。我打开了一个盒子,但还没有看到它被修好。我不得不将所有代码转换为使用javax.faces.*注释,但我计划在它们正常工作后回到CDI


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

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

另一方面,
@ViewScoped