Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean [英] Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean

查看:27
本文介绍了Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得 Java EE 6 规范有点乱.有几组注释.

I feel there is a little mess in the Java EE 6 spec. There are several sets of annotations.

我们有用于创建 EJB 的 javax.ejb 注释,例如 @Stateful@Stateless.

We have javax.ejb annotations like @Stateful and @Stateless for creating EJBs.

还有一个 @javax.annotation.ManagedBean 来创建托管 bean.

There is also a @javax.annotation.ManagedBean to create a managed bean.

javax.enterprise.context 中有@SessionScoped@RequestScoped 等注解.

更何况javax.faces.bean还有@ManagedBean@SessionScoped/@RequestScoped注解代码> 包.

What is more there are also @ManagedBean and @SessionScoped/@RequestScoped annotations in javax.faces.bean package.

为了使事件变得更加复杂,有一个带有 @Named 注释的包 javax.inject.

And to make things event more complicated there is a package javax.inject with @Named annotation.

有人可以描述一下它们之间的关系吗?

Can someone please describe how they are related one to another?

我在哪里可以使用 @EJB@Inject@ManagedPropery 来注入其他 bean?

Where can I use @EJB, @Inject or @ManagedPropery to inject other beans?

推荐答案

首先让我做一些澄清:

托管 bean 定义:通常托管 bean 是一个对象,其生命周期(构造、销毁等)由容器管理.

Managed bean definition : generally a managed bean is an object that its life cycle (construction, destruction, etc) is managed by a container.

在Java ee中,我们有很多管理对象生命周期的容器,比如JSF容器、EJB容器、CDI容器、Servlet容器等.

In Java ee we have many containers that manage life cycle of their objects, like JSF container, EJB container, CDI container, Servlet container, etc.

所有这些容器都是独立工作的,它们在应用服务器初始化时启动并在部署时扫描所有工件的类,包括 jar、ejb-jar、war 和 ear 文件,并收集和存储一些关于它们的元数据,然后当你在运行时需要一个类的对象,他们会给你这些类的实例,完成工作后,他们会销毁它们.

All of these containers work kind of independent, they boot in application server initialization and scan classes of all artifacts including jar, ejb-jar, war and ear files in deployment time and gather and store some metadata about them, then when you need an object of a class at runtime they will give you instances of those classes and after finishing the job, they will destroy them.

所以我们可以说我们有:

So we can say that we have:

  • JSF 托管 bean
  • CDI 托管 bean
  • EJB 托管 bean
  • 甚至 Servlet 也是托管 bean,因为它们由容器实例化和销毁,容器是一个 servlet 容器.

因此,当您看到 Managed Bean 一词时,您应该询问它的上下文或类型.(JSF、CDI、EJB 等)

So when you see the Managed Bean word, you should ask about the context or type of it.(JSF, CDI, EJB, etc.)

然后你可能会问为什么我们有很多这样的容器:AFAIK,Java EE 的人想要一个依赖注入框架,但他们无法在一个规范中收集所有需求,因为他们无法预测未来的需求,他们制作了 EJB1.0,然后是 2.0,然后是 3.0,现在是 3.1,但 EJB 的目标只是满足一些需求(事务、分布式组件模型等).

Then you might ask why we have many of these containers: AFAIK, Java EE guys wanted to have a dependency injection framework, but they could not gather all requirements in one specification because they could not predict the future requirements and they made EJB 1.0 and then 2.0 and then 3.0 and now 3.1 but EJB's target was for just some requirements (transaction, distributed component model, etc).

同时(同时)他们意识到他们也需要支持 JSF,于是他们制作了 JSF 托管 bean 和另一个 JSF bean 容器,他们认为它是一个成熟的 DI 容器,但仍然不完整和成熟容器.

At the same time (in parallel) they realized that they need to support JSF too, then they made JSF managed beans and another container for JSF beans and they considered it a mature DI container, but still it was not complete and mature container.

在那之后 Gavin King 和其他一些好人 ;) 制作了 CDI,这是我见过的最成熟的 DI 容器.CDI(受 Seam2、Guice 和 Spring 的启发)被用来填补 JSF 和 EJB 之间的空白以及许多其他有用的东西,如 pojo 注入、生产者方法、拦截器、装饰器、集成 SPI、非常灵活等,它甚至可以做到EJB 和 JSF 托管 bean 正在做什么,那么我们就可以拥有一个成熟且功能强大的 DI 容器.但是出于某些向后兼容性和政治原因,Java EE 人员希望保留它们!!!

After that Gavin King and some other nice guys ;) made CDI which is the most mature DI container I've seen. CDI (inspired by Seam2, Guice and Spring) was made to fill the gap between JSF and EJB and lots of other useful stuff like pojo injection, producer methods, interceptors, decorators, integration SPI, very flexible, etc. and it can even do what EJB and JSF managed beans are doing then we can have just one mature and powerful DI container. But for some backward compatibility and political reasons Java EE guys want to keep them!!!

您可以在此处找到每种类型的区别和用例:

Here you can find the difference and use cases for each of these types:

JSF 托管 Bean、CDI Bean 和 EJB

JSF 最初是使用自己的托管 bean 和依赖项注入机制开发的,该机制在 JSF 2.0 中得到了增强,以包含基于注释的 bean.当 CDI 与 Java EE 6 一起发布时,它被视为该平台的托管 bean 框架,当然,EJB 已经过时了它们已经存在了十多年.

JSF was initially developed with its own managed bean and dependency injection mechanism which was enhanced for JSF 2.0 to include annotation based beans. When CDI was released with Java EE 6, it was regarded as the managed bean framework for that platform and of course, EJBs outdated them all having been around for well over a decade.

问题当然是知道使用哪个以及何时使用它们.

The problem of course is knowing which one to use and when use them.

让我们从最简单的 JSF 托管 bean 开始.

Let’s start with the simplest, JSF Managed beans.

JSF 托管 Bean

简而言之,如果您正在为 Java EE 6 开发并使用 CDI,请不要使用它们.它们为依赖注入和定义网页的支持 bean 提供了一种简单的机制,但它们的功能远不如 CDI bean.

In short, don’t use them if you are developing for Java EE 6 and using CDI. They provide a simple mechanism for dependency injection and defining backing beans for web pages, but they are far less powerful than CDI beans.

它们可以使用带有可选名称参数的 @javax.faces.bean.ManagedBean 注释来定义.此名称可用于从 JSF 页面引用 bean.

They can be defined using the @javax.faces.bean.ManagedBean annotation which takes an optional name parameter. This name can be used to reference the bean from JSF pages.

可以使用 javax.faces.bean 包中定义的不同范围之一将范围应用于 bean,其中包括请求、会话、应用程序、视图和自定义范围.

Scope can be applied to the bean using one of the different scopes defined in the javax.faces.bean package which include the request, session, application, view and custom scopes.

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

JSF bean 不能在没有某种手动编码的情况下与其他种类的 bean 混合.

JSF beans cannot be mixed with other kinds of beans without some kind of manual coding.

CDI Bean

CDI 是作为 Java EE 6 的一部分发布的 bean 管理和依赖项注入框架,它包括一个完整、全面的托管 bean 工具.CDI bean 远比简单的 JSF 托管 bean 先进和灵活.他们可以使用拦截器、对话范围、事件、类型安全注入、装饰器、构造型和生产者方法.

CDI is the bean management and dependency injection framework that was released as part of Java EE 6 and it includes a complete, comprehensive managed bean facility. CDI beans are far more advanced and flexible than simple JSF managed beans. They can make use of interceptors, conversation scope, Events, type safe injection, decorators, stereotypes and producer methods.

要部署 CDI bean,您必须在类路径上的 META-INF 文件夹中放置一个名为 beans.xml 的文件.一旦你这样做了,那么包中的每个 bean 都变成了一个 CDI bean.CDI 中有很多特性,太多无法在此介绍,但作为 JSF 类特性的快速参考,您可以使用 javax.enterprise 中定义的范围之一来定义 CDI bean 的范围.context 包(即请求、会话、会话和应用程序范围).如果您想从 JSF 页面使用 CDI bean,您可以使用 javax.inject.Named 批注为其命名.要将 bean 注入另一个 bean,请使用 javax.inject.Inject 注释对该字段进行注释.

To deploy CDI beans, you must place a file called beans.xml in a META-INF folder on the classpath. Once you do this, then every bean in the package becomes a CDI bean. There are a lot of features in CDI, too many to cover here, but as a quick reference for JSF-like features, you can define the scope of the CDI bean using one of the scopes defined in the javax.enterprise.context package (namely, request, conversation, session and application scopes). If you want to use the CDI bean from a JSF page, you can give it a name using the javax.inject.Named annotation. To inject a bean into another bean, you annotate the field with javax.inject.Inject annotation.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

上面定义的自动注入可以通过使用限定符来控制,这些限定符可以帮助匹配您想要注入的特定类.如果您有多种付款类型,您可以添加一个限定符来确定它是否是异步的.虽然您可以使用 @Named 注释作为限定符,但您不应该使用它,因为它是为在 EL 中公开 bean 提供的.

Automatic injection like that defined above can be controlled through the use of Qualifiers that can help match the specific class that you want injected. If you have multiple payment types, you might add a qualifier for whether it is asynchronous or not. While you can use the @Named annotation as a qualifier, you shouldn’t as it is provided for exposing the beans in EL.

CDI 通过使用代理来处理范围不匹配的 bean 的注入.因此,您可以将请求范围的 bean 注入会话范围的 bean 中,并且该引用对每个请求仍然有效,因为对于每个请求,代理重新连接到请求范围的 bean 的实时实例.

CDI handles the injection of beans with mismatched scopes through the use of proxies. Because of this you can inject a request scoped bean into a session scoped bean and the reference will still be valid on each request because for each request, the proxy re-connects to a live instance of the request scoped bean.

CDI 还支持拦截器、事件、新的对话范围和许多其他功能,这使其成为比 JSF 托管 bean 更好的选择.

CDI also has support for interceptors, events, the new conversation scope and many other features which makes it a much better choice over JSF managed beans.

EJB

EJB 早于 CDI bean,在某些方面与 CDI bean 相似,但在其他方面非常不同.CDI bean 和 EJB 的主要区别在于 EJB 是:

EJBs predate CDI beans and are in someways similar to CDI beans and in other ways very different. Primarily, the differences between CDI beans and EJBs is that EJBs are :

  • 事务性
  • 远程或本地
  • 能够钝化有状态的 bean 以释放资源
  • 能够使用计时器
  • 可以是异步的

两种类型的 EJB 称为无状态和有状态.无状态 EJB 可以被认为是线程安全的一次性 bean,它不维护两个 Web 请求之间的任何状态.有状态 EJB 确实保持状态,并且可以在需要时被创建和闲置,直到被处理为止.

The two types of EJBs are called stateless and stateful. Stateless EJBs can be thought of as thread safe single-use beans that don’t maintain any state between two web requests. Stateful EJBs do hold state and can be created and sit around for as long as they are needed until they are disposed of.

定义 EJB 很简单,您只需在类中添加一个 javax.ejb.Statelessjavax.ejb.Stateful 注释即可.

Defining an EJB is simple, you just add either a javax.ejb.Stateless or javax.ejb.Stateful annotation to the class.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

无状态 bean 必须有一个依赖范围,而有状态会话 bean 可以有任何范围.默认情况下,它们是事务性的,但您可以使用事务属性注释.

Stateless beans must have a dependent scope while a stateful session bean can have any scope. By default they are transactional, but you can use the transaction attribute annotation.

虽然 EJB 和 CDI bean 在特性方面非常不同,但编写代码来集成它们非常相似,因为 CDI bean 可以注入 EJB,EJB 可以注入 CDI bean.将一种注入另一种时无需进行任何区分.同样,CDI 通过使用代理处理不同的范围.一个例外是 CDI 不支持远程 EJB 的注入,但可以通过为其编写一个简单的生产者方法来实现.

While EJBs and CDI beans are very different in terms of features, writing the code to integrate them is very similar since CDI beans can be injected into EJBs and EJBs can be injected into CDI beans. There is no need to make any distinction when injecting one into the other. Again, the different scopes are handled by CDI through the use of proxying. One exception to this is that CDI does not support the injection of remote EJBs but that can be implemented by writing a simple producer method for it.

可以在 EJB 上使用 javax.inject.Named 注释以及任何限定符以将其与注入点匹配.

The javax.inject.Named annotation as well as any Qualifiers can be used on an EJB to match it to an injection point.

何时使用哪个 bean

你怎么知道什么时候使用哪个 bean?简单.

How do you know when to use which bean? Simple.

除非您在 servlet 容器中工作并且不想尝试让 CDI 在 Tomcat 中工作,否则切勿使用 JSF 托管 bean(尽管有一些 Maven 原型,因此没有任何借口).

Never use JSF managed beans unless you are working in a servlet container and don’t want to try and get CDI working in Tomcat (although there are some Maven archetypes for that so there’s no excuse).

通常,除非您需要 EJB 中可用的高级功能(例如事务功能),否则您应该使用 CDI bean.您可以编写自己的拦截器来使 CDI bean 成为事务性的,但就目前而言,在 CDI 获得即将到来的事务性 CDI bean 之前,使用 EJB 更简单.如果您被困在 servlet 容器中并使用 CDI,那么手写事务或您自己的事务拦截器是没有 EJB 的唯一选择.

In general, you should use CDI beans unless you need the advanced functionality available in the EJBs such as transactional functions. You can write your own interceptor to make CDI beans transactional, but for now, it's simpler to use an EJB until CDI gets transactional CDI beans which is just around the corner. If you are stuck in a servlet container and are using CDI, then either hand written transactions or your own transaction interceptor is the only option without EJBs.

如果你需要在 CDI 中使用 @ViewScoped 你应该

If you need to use @ViewScoped in CDI you should

  • 使用 seam-facesMyFaces CODI 模块.只需将其中之一添加到您的类路径中,@ViewScoped 将在 CDI 中工作.MyFaces CODI 对@ViewScoped 的支持更加稳固
  • 使用MyFaces CODI 的@ViewAccessScoped,它是Apache 在CDI 之上编写的扩展,只需下载 并使用 @ViewAccessScoped 注释而不是 @ViewScoped.
  • 使用 CDI @ConversationScoped 并使其长期运行.请参阅此处了解更多信息.
  • 使用 Omnifaces @ViewScoped 注释
  • use seam-faces or MyFaces CODI module. just add one of them to your classpath and @ViewScoped will work in CDI. MyFaces CODI has an even more solid support of @ViewScoped
  • use MyFaces CODI's @ViewAccessScoped, it is an extension written on top of CDI by Apache, just download it and use @ViewAccessScoped annotation instead of @ViewScoped.
  • Use CDI @ConversationScoped and make it long running. See here for more info.
  • Use Omnifaces @ViewScoped annotation

某些部分从这里窃取.

这篇关于Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆