【问题标题】:Access an injected resource in EJB访问 EJB 中的注入资源
【发布时间】:2013-11-10 10:23:49
【问题描述】:

我目前正在阅读resource injection in the java-ee tutorial 章节,我无法理解注入资源后如何使用资源,或者换句话说,以何种方式可以访问它:

基于字段的注入:

public class SomeClass {
    @Resource(name="customerDB")
    private javax.sql.DataSource myDB;
...
}

基于方法的注入:

public class SomeClass {

    private javax.sql.DataSource myDB;
...
    @Resource(name="customerDB")
    private void setMyDB(javax.sql.DataSource ds) {
        myDB = ds;
    }
...
}

基于类的注入:

@Resource(name="myMessageQueue",
                type="javax.jms.ConnectionFactory")
public class SomeMessageBean {
...
}

我想在class-based 中只有lookup 才有可能(究竟如何?)。然而,在前两种情况下,应该如何使用资源,特别是当它另外定义名称时?

更新:

如果不完全清楚,我的问题涉及以下主题:

1) 在field-method-based injection 中,我是否可以访问以下资源:

myDB.someMethod();

customerDB.someMethod();

如果第一个是正确的,name 的目的是什么?我也可以使用lookup 访问它吗?

2) 我如何在class-based injection 中访问它?我想lookup 但在哪条路径下?

【问题讨论】:

  • 您在 bean 的所有方法中使用注入的字段,就像在任何其他 Java 类中使用任何其他字段一样。我不明白你的问题。
  • @JBNizet:我已经更新了问题。

标签: jakarta-ee resources ejb


【解决方案1】:

如果第一个是正确的,那么这个名字的目的是什么?我也可以通过查找来访问它吗?

JNDI 和大量重载的@Resource 注释的最大困难和混淆的主要原因是name 指的是与组件相关联的本地 ENC 空间(在 EJB bean 的情况下,它是单个豆)。您可以使用 java:comp/env 从初始上下文访问此空间。

'name' 既是目标名称又是源名称。作为目标名称,它不查找内容,而是将内容存储在 ENC 中。如果某些东西已经映射到 ENC,例如通过 XML,然后它用作源名称(用于从 ENC 中查找)。

'lookup' 但是总是按照它所说的去做;它在“GLOBAL”JNDI 命名空间中进行查找,例如java:app/java:module/ 等。请注意,我将 global 放在引号之间,因为即使这些名称空间仍然与完成 JNDI 查找的位置相关。

如何在基于类的注入中访问它?

基于类的注入是 XML 语法的注解等价物,用于将某些东西映射到组件的 ENC。恕我直言,它不能很好地转化为现代编程实践。在向 ENC 注入一些内容后,您可以使用上述java:comp/env 空格通过InitialContext 再次查找它。

例如给定

@Resource(name="myMessageQueue",
                type="javax.jms.ConnectionFactory")
public class SomeMessageBean {
...
}

您可以从方法调用链中的任何位置对 SomeMessageBean 执行以下查找,直到下一次调用 Java EE 组件(设置新的 ENC 上下文):

try {
    ConnectionFactory connectionFactory = new InitialContext().lookup("myMessageQueue");
} catch (NamingException e) {
   ...
}

总而言之,@Resource 是对 Java EE 中注入的古老前体的某种尝试,但由于遗留问题,它本身增加了很多复杂性。恕我直言,如果整个 Java EE 都迁移到 @Inject 会更好,它的语义更清晰且重载更少。

另请参阅:Declaring @Resource and @EJB at the class level in Java EE6

【讨论】:

  • +1 进行解释。所以@Resource(name="foo")实际上是@Resource(name="foo", lookup="foo")的快捷方式,对吗?而且,除了注入字段/方法之外,它还在 ENC 中为全局命名的“foo”资源创建了一个“本地”别名,对吧?
  • 在我看来也很奇怪,“名称”和“查找”完全实现了相同的目的。
  • @JBNizet 基本上,但只是 @Resource(name="foo") 不会查找 foo (作为顶级 JNDI 条目),但只有 java:comp/env/foo 如果它在那里。当同时指定namelookup 时,在类级别使用它确实类似于别名。由于@Resource 的许多重载和有时模棱两可的含义,很难记住所有内容 100% 正确。
  • @arjacsoh >It seems to me also strange that "name" and "lookup" fulfill the same purpose. - 它们是不同的,但我知道这很令人困惑。还有mappedName 让它更加混乱:P
【解决方案2】:

回答你的第一个问题:

@Resource(name="customerDB")
private javax.sql.DataSource myDB;

上面的代码意思是:用名为"customerDB"的DataSource注入私有字段myDB。字段名和资源名是两个完全不同的东西。变量名由你决定,资源名必须是 JNDI 中配置的 DataSource 的名称。

当然,您使用myDB 来访问该字段,因为这就是该字段的名称。注释只是与常规 Java 类、字段和方法相关联的元数据。它们不会改变 Java 的工作方式:要访问一个字段,您可以使用该字段的名称。不是与该字段关联的 Java EE 注释的名称。

关于你的第二个问题,公平地说,我不知道基于类的注入意味着什么以及何时有用。

【讨论】:

    猜你喜欢
    • 2012-05-19
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    相关资源
    最近更新 更多