所有8种原始包装器和String都支持@Resource类型,并且可以通过在标准ejb-jar.xml文件中声明它们来进行查找或注入。
声明名称值(和类型)对
这是通过
<env-entry>部署描述符中的xml元素完成的。
在EJB
3.0中,必须对希望引用相同名称/值对的每个bean执行此操作。这是因为EJB最初的设计与Servlet不同,并且每个EJB实际上都获得了自己的私有JNDI名称空间
java:comp/env,而同一模块中的所有Servlet共享相同的
java:comp/env。
<ejb-jar> <enterprise-beans> <session> <ejb-name>MySessionBean</ejb-name> <env-entry> <env-entry-name>myBoolean</env-entry-name> <env-entry-type>java.lang.Boolean</env-entry-type> <env-entry-value>true</env-entry-value> </env-entry> <env-entry> <env-entry-name>myString</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>hello world</env-entry-value> </env-entry> <env-entry> <env-entry-name>myDouble</env-entry-name> <env-entry-type>java.lang.Double</env-entry-type> <env-entry-value>1.1</env-entry-value> </env-entry> <env-entry> <env-entry-name>myLong</env-entry-name> <env-entry-type>java.lang.Long</env-entry-type> <env-entry-value>12345678</env-entry-value> </env-entry> <env-entry> <env-entry-name>myFloat</env-entry-name> <env-entry-type>java.lang.Float</env-entry-type> <env-entry-value>1.3</env-entry-value> </env-entry> <env-entry> <env-entry-name>myInteger</env-entry-name> <env-entry-type>java.lang.Integer</env-entry-type> <env-entry-value>1024</env-entry-value> </env-entry> <env-entry> <env-entry-name>myShort</env-entry-name> <env-entry-type>java.lang.Short</env-entry-type> <env-entry-value>42</env-entry-value> </env-entry> <env-entry> <env-entry-name>myByte</env-entry-name> <env-entry-type>java.lang.Byte</env-entry-type> <env-entry-value>128</env-entry-value> </env-entry> <env-entry> <env-entry-name>myCharacter</env-entry-name> <env-entry-type>java.lang.Character</env-entry-type> <env-entry-value>D</env-entry-value> </env-entry> </session> </enterprise-beans></ejb-jar>
对于有幸使用EJB
3.1的读者,可以使用全局JNDI并在application.xml中声明它们,然后通过随时随地查找它们
java:app/myString。大多数供应商已经拥有多年的功能,现在终于成为Java
EE 6的标准功能了。
@Resource(lookup="java:app/myString")
Java EE 6中的另一个新功能是支持两种额外的
env-entry-type类型,即java.lang.Class和任何枚举。例如:
<env-entry> <env-entry-name>myPreferredListImpl</env-entry-name> <env-entry-type>java.lang.Class</env-entry-type> <env-entry-value>java.util.ArrayList</env-entry-value></env-entry><env-entry> <env-entry-name>myBillingStragety</env-entry-name> <env-entry-type>java.lang.Class</env-entry-type> <env-entry-value>org.superbiz.BiMonthly</env-entry-value></env-entry><env-entry> <env-entry-name>displayElapsedTimeAs</env-entry-name> <env-entry-type>java.util.concurrent.TimeUnit</env-entry-type> <env-entry-value>MINUTES</env-entry-value></env-entry><env-entry> <env-entry-name>myFavoriteColor</env-entry-name> <env-entry-type>org.superbiz.ColorEnum</env-entry-type> <env-entry-value>ORANGE</env-entry-value></env-entry>
用注入引用它们
以上任何一种都可以通过注入
@Resource。只是不要忘记填写
name属性以匹配
<env-entry-name>
@Statelesspublic 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标准地查找。
@Statelesspublic 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进行查找的功能。它基本上是相同的,但上面有一点糖。
- 在
java:comp/env
不需要前缀 - 不引发检查的异常(对于缺少的名称,将引发EJBException)
Service Locator模式在2003年一直是热门话题,因此我们决定在EJB API中增加一些便利。
@Statelesspublic 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查找过程中可以避免很多缓慢的管道。
当您在上执行“
java:”查询时
InitialContext,调用将通过一堆箍转到VM,以查找谁可以解析该名称,然后最终找到供应商,后者将不得不从线程中查找状态以找出谁提出了要求。以及他们应该获得的命名空间。无论您将什么属性传递给InitialContext,以及供应商在构造时初始化的上下文,它都会在每个调用中执行此操作。“
java:”简单地跳过了所有这些。作为供应商,这是相当令人沮丧的一部分。这也是为什么新的
javax.ejb.embedded.EJBContainerAPI根本不使用
InitialContext任何地方,而只是引用
javax.naming.Context它是一个实际的接口,而不是带有密集且钝的管道的具体“工厂”类的原因。
如果供应商正确执行,那么在SessionContext上进行调用应该会更快。至少在OpenEJB中,所有上述内容(包括ThreadLocal)都将被跳过,并且调用将直接进入已附加到Bean的JNDI名称空间
SessionContext。
避免
InitialContext开销的另一种方法是,只需
java:comp/env在@PostConstruct中查找一次,并保留该结果
Context对象并仅使用它。然后,不要在查找之前添加前缀,
java:comp/env/而直接查找诸如
myString和的名称
myInteger。它将更快,有保证。



