可以使用@Resource在EJB3.0中注入原语吗?
使用Glassfish,我可以设置一个字符串jndi条目:
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 =似乎在内部执行InitialContext.lookup(…)。 但是,这使用ejb3.1,但不幸的是我的prod环境只有ejb3.0。
我想我想弄清楚是否有办法使用@Resource(name =)或@Resource(mappedName =)来做类似的事情? name =似乎是特定于应用程序的,所以我应该能够以某种方式将相对名称映射到全局JNDI名称,但我无法弄清楚映射的注释。
谢谢!
所有8个原始包装器和String都支持@Resource类型,可通过在标准ejb-jar.xml文件中声明它们来查找或注入。
声明名称值(和类型)对
这是通过部署描述符中的
xml元素完成的。
在EJB 3.0中,您必须为希望引用相同名称/值对的每个bean执行此操作。 这是因为EJB最初的设计与Servlet不同,每个EJB实际上都有自己的私有JNDI命名空间java:comp/env
,而同一模块中的所有Servlet共享相同的java:comp/env
。
MySessionBean myBoolean java.lang.Boolean true myString java.lang.String hello world myDouble java.lang.Double 1.1 myLong java.lang.Long 12345678 myFloat java.lang.Float 1.3 myInteger java.lang.Integer 1024 myShort java.lang.Short 42 myByte java.lang.Byte 128 myCharacter java.lang.Character D
对于幸运地使用EJB 3.1的读者,您可以使用全局JNDI并在application.xml中声明它们,并通过java:app/myString
从任何地方查找它们。 大多数供应商多年来一直拥有的function,现在最终成为Java EE 6的标准function。通过@Resource(lookup="java:app/myString")
也可以注入这些条目
Java EE 6中的新function还支持两种额外的env-entry-type
类型,java.lang.Class和任何枚举。 例如:
myPreferredListImpl java.lang.Class java.util.ArrayList myBillingStragety java.lang.Class org.superbiz.BiMonthly displayElapsedTimeAs java.util.concurrent.TimeUnit MINUTES myFavoriteColor org.superbiz.ColorEnum ORANGE
使用Injection引用它们
以上任何一种都可以通过@Resource
注入。 只是不要忘记填写name
属性以匹配
@Stateless public class MySessionBean implements MySessionLocal { @Resource(name="myString") private String striing; @Resource(name = "myDouble") private Double doouble; @Resource(name = "myLong") private Long loong; @Resource(name = "myName") private Float flooat; @Resource(name = "myInteger") private Integer inteeger; @Resource(name = "myShort") private Short shoort; @Resource(name = "myBoolean") private Boolean booolean; @Resource(name = "myByte") private Byte byyte; @Resource(name = "myCharacter") private Character chaaracter; }
使用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引用它们
在EJB 3.0中,作为简化工作的一部分,我们添加了使用javax.ejb.SessionContext
进行查找的function。 它基本上是一样的,但它上面有一点点糖。
-
java:comp/env
前缀不是必需的 - 不会抛出一个已检查的exception(将为缺少的名称抛出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
查找在SessionContext
避免。
当你在InitialContext
上执行’java:’查找时,调用会通过一堆箍来查找谁可以解析该名称,然后最终发送给必须从线程中查找状态的供应商以找出谁问他们应该得到什么名称空间。 无论您传递给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
。 它会更快,更有保障。