@EJBs注解是用来做什么的?

42

我大致知道这个结构的作用:它创建一个SomeType EJB,并将该对象注入到另一个EJB中。

 @EJB(name="name1")
 SomeType someVariable

现在我有一个类,其代码开头如下:(我给出了所有类级别的注释,尽管我认为只有@EJBs是相关的)

@Remote(SomeClass.class)
@Stateless(name="someName")
@EJBs({@EJB(name="name1",beanInterface=Type1.class),
       @EJB(name="name2",beanInterface=Type2.class)})
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class X extends Y{ 
  //code
这里的@EJB是用来做什么的?它们可能从JNDI获取或创建名为"name1"的对象,但结果放在哪里呢?我没有看到任何.lookup调用,但是代码库很庞大,所以我对此不太确定。
附加问题:我认为这两个@Transaction注释只是重复默认值吗?
更新:目前有多人声称@EJBs是专有扩展。事实并非如此。它是Java EE5的核心部分。有关详细信息,请参见JavaDoc。它只是单个@EJB注释的容器。
我相信每个使用EJB注释的人都会查找。我只是想知道此查找的结果会发生什么。

这真是奇怪,我从未听说过@EJBs和这样的用法。 - Amit Deshpande
4个回答

43
@EJB注释(以及@Resource@WebServiceRef等)有两个作用:
  1. 它在组件命名空间中声明一个引用。例如,@EJB(name="myEJB")创建了一个引用java:comp/env/myEJB。如果您对字段进行注释并且未指定名称,则会创建一个引用java:comp/env/com.example.MyClass/myField
  2. 如果注释声明在字段或setter方法上,则容器在组件创建时执行注入。

参考的解析方式因使用场景而异,无论是为了lookup("java:comp/env/myEJB")还是注入:

  1. 如果使用EE 6+,lookup属性需要进行JNDI查找才能解析目标。
  2. 一些应用服务器支持mappedName,这被指定为供应商特定。这通常是通过执行查找来实现的。
  3. 应用服务器支持部署时绑定。这通常是通过执行查找来实现的。
  4. 如果未提供其他绑定信息并且bean接口(beanInterface或字段类型)仅由应用程序中的单个EJB实现,则EJB规范要求其降级为该实现。
  5. 如果未提供其他绑定信息并且第4点不起作用,则某些应用服务器将尝试基于引用名称(例如,java:comp/env/myEJB可能会在服务器命名空间中查找myEJB)。

我有一个Web项目,使用JEE 6和其中的EJBs。当我不需要在@EJB上指定名称属性时,一切都正常。但是,当我把EJBs移动到单独的EJB jar中(仍然是同一个EAR),Weblogic 12.1.2就会告诉我:“ejb-ref没有ejb-link,且目标Bean的JNDI名称未指定”。 - Kalpesh Soni

2
根据这个链接,基本上这个注解使得EJB能够相对于其上下文查找外部EJB。通常,有更加优雅的方法来实现此功能。

2
EJB是Java EE5标准的一部分。请参见此处的javadoc作为证明:http://docs.oracle.com/cd/E17802_01/products/products/ejb/javadoc-3_0-fr/index.html?javax/ejb/EJBs.html。这个javadoc非常清晰:它只是收集了多个EJB注释。我认为你说这些EJB查找是正确的。我的主要问题是:这个查找的结果存储在哪里? - hyperman
谢谢指出,我不知道这是标准的一部分,已更新答案。 - Miljen Mikic

2
Miljen Mikic的答案给了我一个有关可能答案的想法。如果有任何了解JNDI的人看到这篇文章,请告诉我这是否可行,因为我基本上是在猜测。
基本上,查看JNDI树有两种方法:通过全局路径(/some/proprietary/path/my/bean)和通过程序环境(java:comp/env/my/bean)进行查看。其思路是您从全局路径创建引用到您的本地环境,然后从那里查找组件。
所以@Ejb(name="java:comp/env/my/bean",mappedName="/some/proprietary/path/my/bean")将从Java代码(无需描述符XML文件)创建此引用。
这意味着@Ejb(name="java:comp/env/my/bean")本身是无操作的:它将引用复制到自身。它可能具有编译时使应用服务器知道需要此引用的副作用,但仅此而已。

1
关于奖励问题:是的,有关事务的两个注释是重复的默认值:默认的TransactionManagementType是CONTAINER(而不是BEAN),默认的TransactionAttributeType REQUIRED只是说明如果在事务上下文中调用bean,则事务将继续,否则将启动新事务(与REQUIRES_NEW相反,后者将始终创建新的tx)。实际上,这并不像听起来那么简单。参见EJB 3.1规范:“13.3.7为Bean的方法指定事务属性”。“具有容器管理的事务划分的企业bean的Bean提供程序可以指定企业bean方法的事务属性。对于具有容器管理的事务划分的bean的方法的事务属性,默认情况下,事务属性的值是REQUIRED事务属性,在这种情况下,不需要显式指定事务属性。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接