EJB实例的创建及销毁是由容器管理的,因此,new 关键字在EBJ中是不起作用的。要在Bean中使用其他的DJB或资源,必顺通过JNDI(Java Naming and Directory Interface)查找和注入注释。
一、依赖查找(Dependency Lookup)
依赖查找是Java EE依赖管理的传统形式,它是依靠JNDI查找一个命名引用。Java EE支持JNDI,每个组件都有它自已本地范围的JNDI命名上下文--环境命名上下文。EJBContext接口提供了获得这个环境命名上下文的引用,如下:
...
public void setSessionContext(SessionContest contest)
{
this.context=context;
}
...
这样就获得了环境命名上下文,也可以如下
...
public void init()
{
try{
context ctx=new InitaialContext();
audit=(AuditService)ctx.lookup("java:comp/env/audit");
}
}
...
上面写得有些迷糊,采用JNDI查找时,要先给JNDI ENC(Enterprise Nameing Context)添加所要查找的类,ENC就是一个内部注册表,要用资源,先进行注册。注册后就可以用lookup方法进行查找。
应用服务器中的EJB容器有自已的内部注册表,向这个注册表注册也很容易,一般通过ejb-jar.xml,web.wml或注入注释进行注册。
下面引用的黎活明老师教材中的例子:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
<enterprise-beans>
<session>
<ejb-name>InjectionBean</ejb-name>
<ejb-local-ref>
<ejb-ref-name>ejb/HelloWorld</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.foshanshop.ejb3.LocalHello</local>
<ejb-link>HelloBean</ejb-link>
</ejb-local-ref>
</session>
</enterprise-beans>
</ejb-ja
也可以用注解的方式:
@EJB (name="ejb/HelloWorld",beanName="HelloBean,beanInterface=LocalHello.class)
public class ...
接下来就可以从ENC获取资源的引用,可通过注册项名进行JDNI查找,如LocalHello helloworld=(LocalHello) ctx.lookup ("java:com/env/ejb/HelloWorld"),comp代表组件,ja va:comp/env指向EJB的ENC,ejb/HelloWorld是在ENC中定义的注册项名称。
二、依赖注入
因为在使用EJB时,要先向ENC注册,再进行查找,是否存在一种更为简单方便的方法呢?自java5.0后,引用了Annotation,即注解,可以自定义Annotation, 如
public @interface Debug{}
可以看出注解的定义很简单,在里面也可以加入方法,属性,
在用时只要
..
@Debug( 对属性或方法进行赋值)/
...
java.lang.annotatin.Retention类型可以在定义Annotation时指示编译器如何对待自定义的Annotation,一共有三种类型:
SOURCE//编译器处理完Annotation信息就没事了
CLASS,//编译器将Annotation存储于class文件中
RUNTIME,//编译器将Annotation存储于class文件中,可由VM读入,
另外,可以使用@Target,@Documented,@Inherited进行修饰,
Tartget中有TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL-VARIABLE,ANNOTATION-TYPE,PACKAGE进行限定,限定后的注解只要限定词所表求的范围有效,如METHOD在方法内有效。
下面是对EBK注解的定义:
package javax.ejb;
@Target({TYPE,METHOD,FILD})@Retention(rUNTIME)
public @interface DJB
{
String name() default"";//表示被引用的EJB的JNDI ENC注册项名称,相对应于java:comp/env上下文
Class beanInterface() default Object class;//指定使用Bean的接口,如果修饰Bean类,则必对这一项进行赋值,对应于ejb-jar/
//的 <local>...</local>
String beanName() default"";//指定要引用的Bean的名称,对应于ejb-jar/
//的 <ejb-link></ejb-link>
String mappedName() default"";//表示EJB的全局JNDI名,和容器厂商有关,}
在使用时,有四种情况:
1.不带任何属性
当注解的接口只唯一一个Bean使用时,如有多个则会抛出部署异常,
2.带beanName()属性
当有多个Bean实现同一个接口时
3.带name()属性
当只有一个Bean实现这个接口时,效果和第一种情况相同,否则要在配置文件中进行自动添加注册项,或再带上beanName参数。
4.带namppedName()属性
容器会根扰mappedName的值直执着从全局JNDI中查找EJB引用,但为了移植,还是不带的好。