Java @Resource可以用于在EJB3.0中注入原语吗?

Java @Resource可以用于在EJB3.0中注入原语吗?,java,glassfish,ejb-3.0,java-ee-6,ejb-3.1,Java,Glassfish,Ejb 3.0,Java Ee 6,Ejb 3.1,使用Glassfish,我可以设置字符串jndi条目: JNDI name: "com/xyzcompany/echo/EchoServiceBean/viewName" Factory Class: org.glassfish.resources.custom.factory.PrimitivesAndStringFactory Properties: value="Testing123" JNDI名称:“com/xyzcompany/echo/EchoServiceBean/viewName

使用Glassfish,我可以设置字符串jndi条目:

JNDI name: "com/xyzcompany/echo/EchoServiceBean/viewName" Factory Class: org.glassfish.resources.custom.factory.PrimitivesAndStringFactory Properties: value="Testing123" JNDI名称:“com/xyzcompany/echo/EchoServiceBean/viewName” 工厂类:org.glassfish.resources.custom.Factory.PrimitivesAndStringFactory 属性:value=“Testing123” 然后,我可以将这个容器配置的字符串注入我的EJB:

@Resource(lookup = "com/xyzcompany/echo/EchoServiceBean/viewName") String viewName; @资源(lookup=“com/xyzcompany/echo/EchoServiceBean/viewName”) 字符串视图名; lookup=似乎在内部执行InitialContext.lookup(…)。然而,这使用了ejb3.1,但不幸的是,我的prod环境只有ejb3.0

我想我是想弄清楚有没有一种方法可以使用@Resource(name=)或@Resource(mappedName=)来做类似的事情?name=似乎是特定于应用程序的,因此我应该能够以某种方式将相对名称映射到全局JNDI名称,但我不知道是什么注释进行了映射


谢谢

所有8个原语包装器和字符串都受@Resource类型支持,可以通过在标准ejb-jar.xml文件中声明它们来进行查找或注入

声明名称-值(和类型)对 这是通过部署描述符中的
xml元素完成的

在EJB3.0中,必须对希望引用相同名称/值对的每个bean执行此操作。这是因为EJB最初的设计不同于servlet,每个EJB实际上都有自己的私有JNDI命名空间,
java:comp/env
,而同一模块中的所有servlet共享相同的
java:comp/env


MySessionBean
myBoolean
java.lang.Boolean
真的
myString
java.lang.String
你好,世界
我的替身
java.lang.Double
1.1
myLong
java.lang.Long
12345678
我的花车
java.lang.Float
1.3
myInteger
java.lang.Integer
1024
米肖特
java.lang.Short
42
myByte
java.lang.Byte
128
我的性格
java.lang.Character
D
对于有幸使用EJB3.1的读者,您可以使用全局JNDI并在application.xml中声明它们,并通过
java:app/myString
从任何地方查找它们。大多数供应商多年来一直拥有的一个特性现在终于成为JavaEE6的标准。也可以通过
@Resource(lookup=“java:app/myString”)

JavaEE6中的另一个新功能是支持两种额外的
env条目类型,Java.lang.Class和任意枚举。例如:


myPreferredListImpl
java.lang.Class
java.util.ArrayList
myBillingStragety
java.lang.Class
org.superbiz.BiMonthly
显示时间
java.util.concurrent.TimeUnit
会议记录
我最喜欢的颜色
org.superbiz.ColorEnum
橙色
使用注入引用它们 以上任何一项都可以通过
@Resource
注入。只是别忘了填写
name
属性以匹配

使用JNDI引用它们 这些名称还可以通过EJB私有和可移植
java:comp/env
命名空间中的javax.naming.InitialContext进行标准化查找

@Stateless
public class MySessionBean implements MySessionLocal {

    @PostConstruct
    private void init() {

        try {
            final InitialContext initialContext = new InitialContext();// must use the no-arg constructor

            final String myString = (String) initialContext.lookup("java:comp/env/myString");
            final Boolean myBoolean = (Boolean) initialContext.lookup("java:comp/env/myBoolean");
            final Double myDouble = (Double) initialContext.lookup("java:comp/env/myDouble");
            final Long myLong = (Long) initialContext.lookup("java:comp/env/myLong");
            final Float myFloat = (Float) initialContext.lookup("java:comp/env/myFloat");
            final Integer myInteger = (Integer) initialContext.lookup("java:comp/env/myInteger");
            final Short myShort = (Short) initialContext.lookup("java:comp/env/myShort");
            final Byte myByte = (Byte) initialContext.lookup("java:comp/env/myByte");
            final Character myCharacter = (Character) initialContext.lookup("java:comp/env/myCharacter");
        } catch (NamingException e) {
            throw new EJBException(e);
        }
    }
}
使用SessionContext引用它们 在EJB3.0中,作为简化工作的一部分,我们添加了使用
javax.EJB.SessionContext
进行查找的功能。它本质上是一样的,但上面有一点糖

  • java:comp/env
    前缀不是必需的
  • 不引发选中的异常(将引发缺少名称的EJBException)
服务定位器模式在2003年成为热门话题,因此我们决定在EJB API中构建一点便利性

@Stateless
public class MySessionBean implements MySessionLocal {

    @Resource
    private SessionContext sessionContext;

    @PostConstruct
    private void init() {

        final String myString = (String) sessionContext.lookup("myString");
        final Boolean myBoolean = (Boolean) sessionContext.lookup("myBoolean");
        final Double myDouble = (Double) sessionContext.lookup("myDouble");
        final Long myLong = (Long) sessionContext.lookup("myLong");
        final Float myFloat = (Float) sessionContext.lookup("myFloat");
        final Integer myInteger = (Integer) sessionContext.lookup("myInteger");
        final Short myShort = (Short) sessionContext.lookup("myShort");
        final Byte myByte = (Byte) sessionContext.lookup("myByte");
        final Character myCharacter = (Character) sessionContext.lookup("myCharacter");
    }
}
关于IntialContext邪恶的旁注 另外,我可以告诉你,我的供应商帽子戴上后,通过
SessionContext
查找,在引擎盖下可以避免一些缓慢的管道

当您在
InitialContext
上执行“java:'查找”时,调用将通过一系列环转到VM,以找到谁可以解析该名称,然后最终转到供应商,供应商必须从线程中查找状态,以确定询问者和他们应该获得的名称空间。无论您将什么属性传递到InitialContext以及供应商在其构造中初始化了什么上下文,它都会在每次调用中执行此操作。“java:”简单地跳过了这一切。作为一个供应商,这是相当令人沮丧的一部分。这也是为什么新的
javax.ejb.embedded.EJBContainer
API根本不在任何地方使用
InitialContext
,而只是引用
javax.naming.Context
,它是一个实际的接口,而不是一个具体的“工厂”类,具有密集的、可获得的管道

如果供应商做得对,在SessionContext上调用应该会快得多。至少在OpenEJB中,包括ThreadLocal在内的所有上述操作都被跳过,调用直接进入该bean的JNDI名称空间,该名称空间已附加到
SessionContext


另一种避免
InitialContext
开销的方法是只需在@PostConstruct中查找
java:comp/env
一次,并保留生成的
Context
对象并仅使用它。然后不要用
java:comp/env/
作为查找前缀,直接查找名称,如
myString
myInteger
。它会更快,而且是有保证的。

这里有一件奇怪的事情,显然name=可以处理除基本类型以外的所有类型。我可以成功地注入DataSource、WorkManager甚至自定义对象,但不能注入原语。javadoc中没有提到这一点,为什么注入原语不起作用呢?我遇到了完全相同的问题:除了原语之外,我可以注入任何资源。最后,我不得不改变主意
@Stateless
public class MySessionBean implements MySessionLocal {

    @Resource
    private SessionContext sessionContext;

    @PostConstruct
    private void init() {

        final String myString = (String) sessionContext.lookup("myString");
        final Boolean myBoolean = (Boolean) sessionContext.lookup("myBoolean");
        final Double myDouble = (Double) sessionContext.lookup("myDouble");
        final Long myLong = (Long) sessionContext.lookup("myLong");
        final Float myFloat = (Float) sessionContext.lookup("myFloat");
        final Integer myInteger = (Integer) sessionContext.lookup("myInteger");
        final Short myShort = (Short) sessionContext.lookup("myShort");
        final Byte myByte = (Byte) sessionContext.lookup("myByte");
        final Character myCharacter = (Character) sessionContext.lookup("myCharacter");
    }
}