由于 CDI(及其实现 Weld),JEE6 中的每个 POJO 都可以用 注释@Named
,这使得 POJO 可以访问视图。
这是否意味着 ManagedBeans 现在已经完全过时了?还是我错过了@ManagedBean
仍然有意义的东西?
由于 CDI(及其实现 Weld),JEE6 中的每个 POJO 都可以用 注释@Named
,这使得 POJO 可以访问视图。
这是否意味着 ManagedBeans 现在已经完全过时了?还是我错过了@ManagedBean
仍然有意义的东西?
In short, @ManagedBean
makes sense for applications that use JSF but do not use JSR 299 (whatever the reason is). Below a longer explanation from Gavin King:
Re: Comparisons to @ManagedBean annotations in JSF2?:
While looking through the Weld examples, and the older WebBeans documentation, it looks like a competitor to the new @ManagedBean JSF 2.0 annotations. Is there any information on when we'd want to use one over the other?
It's a good question, and I'm not really in full agreement with the answers that have been posted so far.
The new EE Managed Beans specification defines a base component model for Java EE, together with a very basic set of container services (
@Resource
,@PostConstruct
,@PreDestroy
).The idea is that other specifications (beginning with EJB, CDI, JSF and the new Java Interceptors spec) build upon this base component model and layer additional services, for example transaction management, typesafe dependency injection, interceptors. So at this level, the managed beans, CDI, interceptors and EJB specifications all work hand-in-hand and are highly complementary.
Now, the Managed Beans specification is quite open-ended with respect to identifying exactly which classes are managed beans. It does provide the
@ManagedBean
annotation as one mechanism, but it also allows other specifications to define different mechanisms. So, for example:
The EJB specification says that a class obeying certain programming restrictions with a
@Stateless
or@Stateful
annotation deployed in an EJB jar is a managed bean.The CDI specification says that any class with an appropriate constructor deployed in a "bean deployment archive" is a managed bean.
Given that EJB and CDI provide arguably more convenient ways to identify a managed bean, you might wonder precisely what
@ManagedBean
is needed for. The answer, as alluded to by Dan, is that if you have CDI available in your environment (for example, if you are using EE6), then@ManagedBean
is just not really needed.@ManagedBean
is really there for use by people who are using JSF2 without CDI.OTOH, if you do annotate a bean
@ManagedBean
, and you do have CDI in your environment, you can still use CDI to inject stuff into your bean. It's just that the@ManagedBean
annotation is not required in this case.To summarize, if you do have CDI available to you, it provides a far superior programming model to the
@ManagedBean
/@ManagedProperty
model that JSF2 inherits from JSF1. So superior, in fact, that the EE 6 web profile does not require support for@ManagedProperty
etc. The idea being that you should just use CDI instead.
你有一个选择。使用 JSF2 中的 @ManagedBean 将 bean 绑定到表单中,或者使用 CDI 中的 @Named 注释。如果你打算只做 JSF,你可以坚持@ManagedBean,但如果你想与 EJB 集成,或者使用 CDI 的 @ConversationScoped,那就走 CDI 路线。
我个人认为 JSF 的下一个版本应该弃用 @ManagedBean,并在 CDI 上标准化。这种二元性让新手感到困惑。
CDI 没有视图范围,因为它没有视图的概念,所以如果您需要该范围,纯粹形式的 CDI 无法做到。视图范围基本上意味着请求范围 + AJAX-ready。它不是一个 JSF 视图,就像一个名为 的页面xyz.xhtml
,即使您看到 JSF<f:viewParam>
等。视图范围 bean 的一个常见用例是如何将 GET 参数获取到这样的 bean中。也读这个。
请注意,CDI 位于 EJB/服务层而不是 JSF/表示层。这个博客有一个很好的概述。
因此@ManagedBean
,如果您使用 bean,则不能完全被 CDI 取代@ViewScoped
- 至少在没有扩展 CDI或使用Seam 3 Faces 模块的情况下不能。在使用基于 AJAXed JSF 2 的 GUI 工具包(如 RichFaces、PrimeFaces、IceFaces 等)时,几乎总是会使用视图范围的 bean。
在使用 RichFaces 或类似 API 时,混合来自错误 Java EE 6 包的注解可能会给您带来意想不到的麻烦:
@javax.faces.bean.ManagedBean
@javax.faces.bean.[Jsf]Scoped
用于仅在表示层使用的组件,这里是 RichFaces、PrimeFaces 等。一些丰富的组件似乎在使用 CDI 注释和 JSF 注释的辅助 bean 时存在问题。如果您的 bean(或似乎什么都不做的 bean)出现奇怪的行为,则可能是注释的错误组合。
混合 JSF 和 CDI,例如
@javax.inject.Named
@javax.faces.bean.[Jsf]Scoped
当从 JSF 页面引用时,在大多数情况下是可能的并且有效,但是有一些鲜为人知的问题/缺点,例如,当使用 CDI 没有的 JSF 范围时:
此外,该组合
@Named @ViewScoped
不会按预期工作。JSF@ViewScoped
-specific 仅与 JSF-specific 结合使用@ManagedBean
。您的 CDI 特定的@Named
行为将像@RequestScoped
这种方式。使用@ManagedBean
代替@Named
或使用特定于 CDI 的@ConversationScoped
而不是@ViewScoped
.
然后
@javax.inject.Named
@javax.faces.bean.[Cdi]Scoped
可用于直接从您的 JSF 页面 AFAIK 引用的 CDI bean。到目前为止,我对上述组合没有任何问题,所以你可以@ManagedBean
在这里考虑过时。
剩下的是服务层,这里主要是事务性 EJB 服务 bean 声明为
@javax.ejb.*
主要是@javax.ejb.Stateless。您甚至可以直接从 JSF 页面注释和使用 EJB——尽管我不确定这种设计是否可取。要引用(注入)任何带有@javax.ejb.* 注释的组件,例如@Stateless
,更喜欢@Inject
这里@EJB
描述的。(可能是这个答案的祖先......)
最后,可以在这里找到关于 Java EE 6 注释的非常好的概述: http ://www.physics.usyd.edu.au/~rennie/javaEEReferenceSheet.html
注意:以上信息不是来自专家,而只是我自己从新手的角度对这个可笑的令人困惑的 Java EE 6 注释意大利面条的看法。更多的洞察力还有待开发。我希望这个答案能够成为对这种困惑的一般、实用的答案——即使在原始问题的背景下它已经有点过火了。
正如我刚刚在Weld Reference (p. 12) 中读到的,@ManagedBean 现在是多余的:
您可以通过注释 bean 类 @ManagedBean 来显式声明托管 bean,但在 CDI 中您不需要。根据规范,CDI 容器将任何满足以下条件的类视为托管 bean:
- 它不是一个非静态的内部类。它是一个具体的类,或者被注释为@Decorator。
- 它没有使用定义 EJB 组件的注释进行注释,也没有在 ejb-jar.xml 中声明为 EJB bean 类。
- 它没有实现 javax.enterprise.inject.spi.Extension。
- 它有一个合适的构造函数——要么:
- 该类有一个没有参数的构造函数,或者
- 该类声明了一个带有 @Inject 注释的构造函数。