我觉得Java EE 6规范有点混乱。有几组注释。
我们有和javax.ejb
一样的注释@Stateful,@Stateless
用于创建EJB。
还有一个@javax.annotation.ManagedBean
用于创建托管bean
的。
在javax.enterprise.contextlike @SessionScoped
和中有注释@RequestScoped
。
软件包中还有/ @ManagedBean
和注解。@SessionScoped@RequestScopedjavax.faces.bean
为了使事情变得更复杂,有一个javax.inject
带有@Named
注释的程序包。
有人可以描述他们之间的关系吗?
我在哪里可以使用@EJB
,@Inject
或者@ManagedPropery
注入其他bean?
首先让我做一些澄清:
Managed bean definition:通常,托管bean是一个对象,其生命周期(构造,销毁等)由容器管理。
在Java ee中,我们有许多容器可以管理其对象的生命周期,例如JSF容器,EJB容器,CDI容器,Servlet容器等。
所有这些容器都是独立工作的,它们在应用程序服务器初始化中启动,并在部署时扫描所有工件的类,包括jar,ejb-jar,war和ear文件,并收集和存储有关它们的一些元数据,然后在需要时使用对象一个类在运行时将为你提供这些类的实例,完成工作后,它们将销毁它们。
所以我们可以说我们有:
因此,当你看到Managed Bean单词时,应该询问其上下文或类型(JSF,CDI,EJB等)。
然后,你可能会问为什么我们有许多这样的容器:AFAIK,Java EE专家们想要一个依赖项注入框架,但是由于他们无法预测未来的需求并且他们制作了EJB 1.0,因此他们无法在一个规范中收集所有需求。 2.0,然后是3.0,现在是3.1,但是EJB的目标只是满足某些要求(事务,分布式组件模型等)。
同时(并行),他们意识到他们也需要支持JSF,然后他们制作了JSF管理的bean和另一个JSF bean的容器,他们认为它是成熟的DI容器,但是它仍然不是完整而成熟的容器。
之后,加文·金(Gavin King)和其他一些好人;)制造了CDI,这是我见过的最成熟的DI容器。CDI(受Seam2,Guice和Spring的启发)的产生是为了填补JSF和EJB以及许多其他有用的东西(例如pojo注入,生产者方法,拦截器,装饰器,集成SPI,非常灵活等)之间的空白,它甚至可以做到EJB和JSF托管bean所做的事情,那么我们只有一个成熟而强大的DI容器。但是出于某些向后兼容性和政治原因,Java EE专家希望保留它们!!!
在这里,你可以找到每种类型的区别和用例:
JSF托管Bean,CDI Bean和EJB
JSF最初是用自己的托管bean和依赖项注入机制开发的,JSF 2.0对它进行了增强,以包括基于注释的bean。当CDI与Java EE 6一起发布时,它被视为该平台的托管bean框架,当然,EJB已经淘汰了十多年。
当然,问题在于知道使用哪个以及何时使用它们。
让我们从最简单的JSF托管bean开始。
JSF Managed Beans
简而言之,如果你正在为Java EE 6开发并使用CDI,请不要使用它们。它们提供了一种简单的机制来进行依赖项注入和为Web页面定义后备bean,但是它们远没有CDI bean强大。
可以使用@javax.faces.bean.ManagedBean
带有可选name参数的注释来定义它们。该名称可用于引用JSF页面中的bean。
可以使用javax.faces.bean
包中定义的不同范围之一将范围应用于Bean ,包括请求,会话,应用程序,视图和自定义范围。
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
如果没有某种手动编码,则JSF bean无法与其他类型的bean混合。
CDI Beans
CDI是作为Java EE 6的一部分发布的bean
管理和依赖项注入框架,它包括一个完整,全面的托管bean功能。CDI bean比简单的JSF托管bean更先进,更灵活。他们可以利用拦截器,对话范围,事件,类型安全注入,修饰符,构造型和生产者方法。
要部署CDI bean,必须在类路径的META-INF文件夹中放置一个名为beans.xml的文件。完成此操作后,程序包中的每个bean都会变成一个CDI bean。CDI中有很多功能,这里没有太多要介绍的内容,但是作为类似JSF的功能的快速参考,你可以使用包中定义的范围之一javax.enterprise.context(即,请求,对话)来定义CDI bean的范围。,会话和应用范围)。如果要在JSF页面中使用CDI bean,则可以使用javax.inject.Named
批注为其命名。要将一个bean注入另一个bean,请使用注释对字段进行javax.inject.Inject
注释。
@Named("someBean")
@RequestScoped
public class SomeBean {
@Inject
private SomeService someService;
}
如上定义的自动注入可以通过使用限定符来控制,这些限定符可以帮助匹配要注入的特定类。如果你有多种付款方式,则可以添加一个限定符来确定它是否异步。虽然可以将@Named注释用作限定符,但不应将其用作在EL中公开Bean的方法。
CDI通过使用代理来处理范围不匹配的bean的注入。因此,你可以将请求范围的Bean注入会话范围的Bean中,并且引用对每个请求仍然有效,因为对于每个请求,代理都重新连接到请求范围的Bean的活动实例。
CDI还支持拦截器,事件,新的对话范围和许多其他功能,这使其比JSF托管Bean更好。
EJB
EJB早于CDI Bean,并且在某种程度上类似于CDI Bean,但在其他方面却大不相同。首先,CDI bean和EJB之间的区别在于EJB是:
两种类型的EJB称为无状态和有状态。无状态EJB可以看作是线程安全的一次性bean,它在两个Web请求之间不维护任何状态。有状态EJB确实保持状态,并且可以根据需要创建和放置,直到它们被处置为止。
定义EJB很简单,你只需在类中添加javax.ejb.Stateless
或javax.ejb.Stateful
注释。
@Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
无状态bean必须具有从属范围,而有状态会话bean可以具有任何范围。默认情况下,它们是事务性的,但是你可以使用事务属性注释。
尽管EJB和CDI Bean在功能方面非常不同,但是编写代码以将它们集成在一起非常相似,因为CDI Bean可以注入EJB中,而EJB可以注入CDI Bean中。将一个注入另一个时,无需进行任何区分。同样,CDI通过使用代理来处理不同的作用域。一个例外是CDI不支持注入远程EJB,但是可以通过为其编写简单的生产者方法来实现。
javax.inject.Named
以及任何限定符可在一个EJB使用注释来匹配到注入点。
何时使用哪种豆
你如何知道何时使用哪个bean?简单。
除非你在servlet容器中工作并且不想尝试使CDI在Tomcat中工作,否则切勿使用JSF托管bean(尽管有一些Maven原型,所以没有任何借口)。
通常,除非需要EJB中可用的高级功能(例如事务功能),否则应使用CDI bean。你可以编写自己的拦截器以使CDI bean具有事务性,但是就目前而言,使用EJB更为简单,直到CDI即将到来的事务CDI bean。如果你被困在servlet容器中并且正在使用CDI,那么没有EJB的唯一选择是手写事务或你自己的事务拦截器。
如果你需要@ViewScoped
在CDI中使用,则应
@ViewScoped
在CDI中使用。MyFaces CODI
对@ViewScoped
的支持更加可靠MyFaces CODI @ViewAccessScoped
,它是Apache在CDI之上编写的扩展,只需下载它并使用@ViewAccessScoped
注解代替@ViewScoped
。CDI @ConversationScoped
并使其长期运行。有关更多信息,请参见此处。Omnifaces @ViewScoped
批注我使用的是Glassfish 3.1.2.2,JavaEE6。 我有一个库,其中一个类使用CDI获取一个帮助器类。我希望在一个使用该库的特定项目中,重写该CDI依赖项,并强制该库使用我自己的帮助器类,而不是特定于该项目的帮助器类。我可以随意修改库,但默认情况下它应该使用默认的助手类,这样库的其他用户的行为就不会改变。 这应该是CDI模式的完美应用,我为helper类API做了一个java接口;库中
问题内容: 我试图了解该软件包,但不清楚应将注释用于什么目的。Javadoc没有解释其背后的想法。 Javadoc位于http://download.oracle.com/javaee/6/api/javax/inject/Named.html 我正在使用 Spring 3.0 编写一些示例程序,通过放在一个bean上似乎将其添加到bean工厂中,但是Javadoc的描述是如此之轻,我无法分辨这是
问题内容: 我当前正在创建一个EJB3数据访问类,以处理Java EE 6应用程序中的所有数据库操作。现在,由于Java EE 6提供了新的注释,所以我想知道EJB应该具有什么状态,或者它应该是无状态的。 让DAO成为会话Bean还是Bean 会更好?那呢 这些与DAO相关的选项之间有什么区别? 编辑: 我在完整的Java EE 6平台上使用Glassfish 3.0.1 问题答案: 最好让DAO
显式bean归档是包含beans.xml文件[..]的归档。隐式bean归档是包含一个或多个带有bean定义注释[..]的bean类的任何其他归档。 如果我的归档没有描述符文件,我仍然可以使用具有“bean定义注释”的bean。问题是,什么是bean定义注释? CDI规范第2.5节“bean定义注释”说: 容器必须只在CDI规定的范围内支持用javax.inject.inject注释注释的注入点。
当我在Eclipse中通过ejb-javaee6原型创建ejb项目时,我会遇到以下错误: 描述资源路径位置类型背书目录'/home/hFluz/workspace/maven-test/web2/目标/背书'丢失。您可能需要执行Maven命令行构建才能创建它。pom.xml /web228行Maven配置问题 说明资源路径位置类型插件执行未包含在生命周期配置中:org。阿帕奇。专家插件:maven
在C语言中,假设每个算法被赋予完全相同的一组进程,那么先到先得、最短作业优先和循环之间的周转时间是否相等?还是调度算法不同?