EJB3.0入门经典(笔记) - 第2章 EJB知识与运行环境设置(2)

来源:互联网 发布:linux inittab 编辑:程序博客网 时间:2024/06/05 03:58

2 EJB知识与运行环境设置(2

 

 

(上接第2章的第1部分)

 

16.   改变JNDI名称

1) 对于JBoss应用服务器,可以使用JBoss提供的@LocalBinding@RemoteBinding注释来指定会话BeanJNDI名称。例如:

@RemoteBinding(jndiBinding=”foshanShop/RemoteOperation”)

@LocalBinding(jndiBinding=”foshanShop/LocalOperation”)

2) 对于WebLogicSunApplication ServerGlassfish等应用服务器,可以使用@StatelessmappedName()属性设置Bean的全局JNDI名称。例如:

@Stateless(mappedName=”OperationBeanRemote”)

3) 为了避免JNDI名称与厂商相关而造成的移植问题,建议使用ejb-jar.xml部署描述文件进行定义。该文件必须置于jarMETA-INF目录下。

 

 

17.   会话Bean的生命周期事件

1) @PostConstruct

适用于有状态和无状态会话Bean。当Bean实例化完成后,标注了这个注释的回调方法会被立即调用,且仅此一次调用。每个Bean类只能定义一个@PostConstruct方法。

2) @PreDestroy

适用于有状态和无状态会话Bean。当容器销毁一个无用的或者超时的Bean实例时,标注了这个注释的回调方法会被调用,且仅此一次调用。每个Bean类只能定义一个@ PreDestroy方法。

3) @PrePassivated

适用于有状态会话Bean。当Bean实例被钝化之前,具有该注释的回调方法会被调用。如果钝化期间,客户端仍然长期没有对Bean实例进行操作,则容器会从硬盘上删除它。此后,任何针对这个Bean实例方法的调用,都会导致异常。

4) @PostActivated

适用于有状态会话Bean。当Bean实例从钝化状态被激活时,容器会重新实例化一个新的Bean实例,并从硬盘恢复钝化之前的状态。完成激活之后,具有该注释的回调方法会被调用。

5) @Init

用于指定有状态会话Bean的初始化方法。其与@PostConstruct的区别在于,有状态会话Bean中可以存在多个@Init标注的方法。@PostConstruct@Init之后被调用。

6) @Remove

当客户端调用了标注为@Remove的方法时,容器会在方法执行结束后,删除Bean实例。

7) 对于上面的注释方法,必须是void,不带参数的,不抛检查异常的方法。

8) @PostActivate@PostConstruct@PrePassivate@PreDestroy之间实质上并无很大差别。

l           @PostActivate@PostConstruct通常都应该用于初始化或恢复无法序列化的资源,比如数据库连接;

l           @PrePassivate@PreDestroy通常都应该用于关闭无法序列化的资源。因为进入钝化状态后,当Bean实例超时,容器在清除Bean实例之前,是不会调用@PreDestroy方法关闭尚处于打开状态的资源的,比如数据库连接。

 

 

18.   拦截器用于封装应用的公用行为,可以拦截会话Bean和消息驱动Bean的方法调用或生命周期事件。

 

19.   开发拦截器

1) @AroundInvoke注释

l          该注释用于指定用作拦截器的方法。拦截器方法与被拦截的业务方法在同一个Java调用堆栈、同一个事务和安全上下文中。

l          @AroundInvoke标识的方法必须遵守以下格式:

public Object methodName(javax.interceptor.InvocationContextctx) throws Exception

2) InvocationContext

此上下文接口封装了关于客户端所调用业务方法的一些信息:

l           getTarget():返回Object,指向被调用的Bean实例。

l           getMethod():返回Method,指向被拦截的业务方法。

l           getParameters():返回Object[]数组,指向被拦截业务方法的参数。

l           setParameters():返回void,设置被拦截业务方法的参数。

l           getContextData():返回Map<String,Object>,在整个方法调用期间都可以访问。同一方法调用内的不同拦截器之间可以利用这个Map来传递上下文相关的数据。

3) proceed方法,返回Object

l           InvocationContextproceed()方法内部会继续调用后面拦截器的@AroundInvoke方法,直到所有的拦截方法全都被调用以后,才会执行被拦截的业务方法。(个人感觉,有点像FilterChaindoFilter方法)

l           proceed()方法必须在拦截器代码中调用,否则被拦截的业务方法最终就无法被调用到。

l           如果想在被拦截的业务方法执行结束后在执行一些自定义的代码,可以在proceed执行后、拦截器方法返回之前加入自己的代码。

4) 因为拦截器方法和被拦截的业务方法处于相同的java调用堆栈,因此可以通过抛出异常,来终止方法的执行。

5) 除了在外部类中定义拦截器方法,还可以在会话Bean内部将Bean的一个或多个方法定义为拦截器。仍然是使用@AroundInvoke和上述的那种方法格式。执行流程也是一样的。

 

20.   使用拦截器

1) 使用外部类类型的拦截器,可以用@Interceptors注释。这个注释接受拦截器类的.class属性值,多个.class通过逗号分隔。可以标识在类级,表明拦截类中的所有方法;也可以标识在方法级,表明只对某一方法进行拦截。

2) 如果是在Bean类内部,将方法标识为@AroundInvoke,则该方法将会拦截Bean中的所有方法。

3) 默认拦截器

l           通过ejb-jar.xml可以定义默认拦截器,ejb-jar.xml文件需要置于jar文件的META-INF目录:

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"

     xmlns:xml="http://www.w3.org/XML/1998/namespace"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd ">

 

     <assembly-descriptor>

        <interceptor-binding>

       <ejb-name>*</ejb-name>

<interceptor-class>cn.gengv.ejb3ex.interceptor.LogInterceptor</interceptor-class>

        </interceptor-binding>

     </assembly-descriptor>

</ejb-jar>

 

l           <ejb-name>*</ejb-name>指明拦截所有的EJB的所有方法。如果只想拦截某一个EJB,则可以用这个EJB的名称替换通配符“*”。其效果和在Bean类上标识@Interceptor的效果是一样的。

l           <intercepter-class>用来指定拦截器类。

 

4) 禁用拦截器

l           可以使用@ExcludeDefaultInterceptors注释来禁用默认拦截器,该注释可以标识在Bean类级或业务方法级。

l           虽然可以通过@ExcludeDefaultInterceptors注释来禁用默认拦截器,Bean类仍然可以通过@Interceptors注释来使用自己所需要的拦截器。

 

5) 拦截生命周期事件

l           与定义@AroundInvoke方法非常类似,只是使用回调注释,替代@AroundInvoke。例如:

@PostConstruct public voidmethodName(InvocationContext ctx)

l           因为生命周期事件的回调方法没有返回值,因此拦截方法也必须是void。而且拦截方法不能有throws子句。

l           其他特性和@AroundInvoke拦截方法相同。

 

6) 根据自己的测试,默认拦截器会在Bean自己指定的拦截器之前调用

 

 

原创粉丝点击