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

查看:205
本文介绍了Java EE 6 @ javax.annotation.ManagedBean与@ 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.

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

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

还有 @ManagedBean @SessionScoped / @RequestScoped javax.faces.bean 包中的注释。

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

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

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?

推荐答案

首先让我做了一些澄清:

First of all let me do some clarifications:

托管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.

S. o我们可以说我们有:

So we can say that we have:


  • JSF托管bean

  • CDI托管bean

  • EJB托管bean

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

  • JSF managed beans
  • CDI managed beans
  • EJB managed beans
  • And even Servlets are managed beans because they are instantiated and destroyed by a container, which is a servlet container.

因此,当您看到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人员希望有一个依赖注入框架,但他们无法收集一个规范中的所有要求,因为他们可以不预测未来的需求,他们制作了EJB 1.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 b的另一个容器eans和他们认为它是一个成熟的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托管豆,CDI Bean和EJB

JSF最初是用自己开发的托管bean和依赖注入机制,它针对JSF 2.0进行了增强,以包含基于注释的bean。当CDI与Jav​​a 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 Managed bean开始。

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

JSF托管豆

简而言之,如果您正在为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.

它们可以使用<$ c来定义$ c> @ javax.faces.bean.ManagedBean 注释,它带有一个可选的name参数。此名称可用于从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.

可以使用中定义的不同范围之一将范围应用于bean javax.faces.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 Beans

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,必须放置一个名为beans的文件.xml在类路径上的META-INF文件夹中。一旦你这样做,那么包中的每个bean都变成了一个CDI bean。 CDI中有很多功能,这里有很多功能,但作为类似JSF功能的快速参考,您可以使用 javax中定义的一个范围来定义CDI bean的范围。 .enterprise.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 :


  • Transactional

  • 远程或本地

  • 能够消除有状态的bean释放资源

  • 能够使用计时器

  • 可以异步

  • Transactional
  • Remote or local
  • Able to passivate stateful beans freeing up resources
  • Able to make use of timers
  • Can be asynchronous

这两种类型的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.Stateless javax.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.

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

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容器中工作并且不想尝试在Tomcat中使用CDI,否则永远不要使用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-faces MyFaces CODI 模块。只需将其中一个添加到您的类路径中, @ViewScoped 将在CDI中运行。 MyFaces CODI对@ViewScoped的支持更加坚实

  • 使用MyFaces CODI的 @ViewAccessScoped ,它是在CDI上编写的扩展名通过Apache,只需下载它并使用 @ViewAccessScoped 注释而不是 @ViewScoped

  • 使用CDI @ConversationScoped 并让它长时间运行。有关详细信息,请参见此处

  • 使用 Omnifaces @ViewScoped annotation

  • 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与@ javax.inject.Named vs. @ javax.faces.ManagedBean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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