EJB 3.x 拦截器

EJB 3.x 拦截器

拦截器是一种在调用 Enterprise JavaBeans (EJB) 的业务方法或发生 EJB 的生命周期事件时自动调用的方法。

有三种类型的拦截器方法:业务方法拦截器、超时方法拦截器(在 EJB 3.1 中新增)以及生命周期回调拦截器。业务方法拦截器是围绕对某一业务方法的调用来进行调用。超时方法拦截器是围绕对某一 EJB 超时方法的调用来进行调用。生命周期回调拦截器是围绕 PostConstruct、PreDestroy、PrePassivate 或 PostActivate 生命周期事件来进行调用。对于每个拦截器类型,个别类仅能声明一个拦截器方法。但是,类层次结构中的每个类可以为每个拦截器类型声明一个拦截器方法。如果子类中的拦截器方法覆盖了超类中的相同方法,那么仅调用子类中的方法。

允许拦截器方法访问和调用允许关联方法调用的所有资源和组件。此外,拦截器方法还通过与关联方法使用相同的事务和安全上下文来执行。除了单独会话 Bean 之外,生命周期拦截器方法将使用本地事务包含范围 (LTC) 来执行。

您可以直接在 EJB 类或单独拦截器类中声明拦截器方法。要在单独类中声明拦截器方法,您必须使用注释或 XML 将拦截器类绑定到 EJB。使用以下示例来声明拦截器(使用注释):

@Interceptors({ClassInterceptor1.class, ClassInterceptor2.class})
public class TestBean { /* ... */ }

@Interceptors({ClassInterceptor1.class})
public class TestBean2 {
	@Interceptors({MethodInterceptor1.class, MethodInterceptor2.class})
	public void businessMethod() { /* ... */ }
}

使用以下示例来声明拦截器(使用部署描述符):

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <interceptor-class>ClassInterceptor1</interceptor-class>
      <interceptor-class>ClassInterceptor2</interceptor-class>
    </interceptor-binding>

    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <interceptor-class>ClassInterceptor1</interceptor-class>
    </interceptor-binding>

    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <interceptor-class>MethodInterceptor1</interceptor-class>
      <interceptor-class>MethodInterceptor2</interceptor-class>
           <method>
        <method-name>businessMethod</method-name>
           </method>
    </interceptor-binding>
  </assembly-descriptor>

您可以通过在部署描述符中使用 ExcludeClassInterceptors 注释或 exclude-class-interceptors 元素以从方法中排除类级别拦截器。使用以下示例以从方法 businessMethod 中排除拦截器 ClassInterceptor。

@Interceptors({ClassInterceptor1.class})
public class TestBean2 {
	@ExcludeClassInterceptors
	public void businessMethod() { /* ... */ }

	public void businessMethodWithClassInterceptor1() { /* ... */
}

使用以下示例从方法中排除拦截器(使用部署描述符):

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <exclude-class-interceptors>true</exclude-class-interceptors>
           <method>
        <method-name>businessMethod</method-name>
           </method>
    </interceptor-binding>
  </assembly-descriptor>

拦截器方法可以具有公共、受保护、包专用或私有可视性。拦截器方法不能是 final 或 static。业务方法拦截器和超时方法拦截器必须具有返回类型 java.lang.Object、单个参数 javax.interceptor.InvocationContext 和单个抛出字句类型 java.lang.Exception。所有生命周期拦截器必须具有返回类型 void 并且不得具有抛出子句。直接在 EJB 类上声明的生命周期拦截器不得具有参数;在 EJB 超类或拦截器类上声明的生命周期拦截器必须具有单个参数 javax.interceptor.InvocationContext。超时拦截器方法和生命周期拦截器方法不得抛出应用程序异常。

您可以使用拦截器方法的 InvocationContext 参数来获取有关正在调用的方法的信息。getTarget 方法返回正在调用的 Bean 实例。getTimer 方法仅适用于超时方法拦截器,并且此方法返回正在执行的计时器。getMethod 方法返回正在调用的业务接口方法。getParameters 方法返回正在传递到业务方法的参数,setParameters 方法允许修改参数。getContextData 方法返回与正在调用的方法相关联的数据。最后,proceed 方法调用下一个拦截器或 target 方法。

您可以使用注释或 XML 来声明拦截器方法。要使用注释来声明拦截器方法,请在拦截器方法上放置相应的 AroundInvoke、AroundTimeout、PostConstruct、PreDestroy、PrePassivate 或 PostActivate 注释。使用以下示例在 EJB 类上声明业务方法拦截器、超时方法拦截器和 PostConstruct 生命周期拦截器方法(使用注释)。

@Interceptors({ClassInterceptor.class})
public class TestBean {
	@PostConstruct
	private void beanPostConstruct() { /* ... */ }

	@AroundInvoke
	protected Object beanAroundInvoke(InvocationContext ic) throws Exception {
		return ic.proceed();
	}

        @AroundTimeout
        protected Object beanAroundTimeout(InvocationContext ic) throws Exception {
		return ic.proceed();
        }
}

使用以下示例在拦截器类上声明相同拦截器方法。

public class ClassInterceptor {
	@PostConstruct
	private void interceptorPostConstruct(InvocationContext ic) {
		try {
			session.invalidate();
		} catch (Exception ex) { /* ... */ }
	}

	@AroundInvoke
	protected Object interceptorAroundInvoke(InvocationContext ic) throws Exception {
		return ic.proceed();
	}

	@AroundTimeout
	protected Object interceptorAroundTimeout(InvocationContext ic) throws Exception {
		return ic.proceed();
	}
}

或者,您也可以在部署描述符中通过 around-invoke、around-timeout、post-construct、pre-destroy、pre-passivate 和 post-activate 元素来声明拦截器方法。使用以下示例在 EJB 类和拦截器类上声明业务方法拦截器、超时方法拦截器和 PostConstruct 生命周期拦截器方法(使用部署描述符)。

  	<enterprise-Beans>
    <session>
      <ejb-name>TestBean</ejb-name>
      <around-invoke>
        <method-name>beanAroundInvoke</method-name>
      </around-invoke>
      <around-timeout>
        <method-name>beanAroundTimeout</method-name>
      </around-timeout>
      <post-construct>
        <lifecycle-callback-method>beanPostConstruct</lifecycle-callback-method>
      </post-construct>
    		</session>
  </enterprise-beans>

  <interceptors>
    <interceptor>
      <interceptor-class>ClassInterceptor</interceptor-class>
      <around-invoke>
        <method-name>interceptorAroundInvoke</method-name>
      </around-invoke>
      <around-timeout>
        <method-name>interceptorAroundTimeout</method-name>
      </around-timeout>
      <post-construct>
        <lifecycle-callback-method>interceptorPostConstruct</lifecycle-callback-method>
      </post-construct>
    </interceptor>
  </interceptors> 

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <interceptor-class>ClassInterceptor</interceptor-class>
    </interceptor-binding>
  </assembly-descriptor>

您还可以在超类上声明拦截器方法。要使用以下示例在 Bean 超类上声明 PostActivate 拦截器(使用注释):

public class TestBean extends BeanSuperClass { /* ... */ }

public class BeanSuperClass {
	@PostActivate
	private void beanSuperClassPostActivate(InterceptorContext ic) {
		try {
			session.invalidate();
		} catch (Exception ex) { /* ... */ }
	}
}

使用以下示例在拦截器类的超类上声明同一个拦截器方法(使用注释):

public class ClassInterceptor extends InterceptorSuperClass { /* ... */ }

public class InterceptorSuperClass {
	@PostActivate
	private void interceptorSuperClassPostActivate(InterceptorContext ic) {
		try {
			session.invalidate();
		} catch (Exception ex) { /* ... */ }
	}
}

您还可以使用部署描述符来声明相同拦截器方法。使用以下示例在 Bean 和拦截器类的超类上声明拦截器方法:

	<enterprise-Beans>
  <session>
    <ejb-name>TestBean</ejb-name>
    <post-activate>
      <class>BeanSuperClass</class>
	 <lifecycle-callback-method>beanSuperClassPostActivate</lifecycle-callback-method>
    </post-activate>
  		</session>
 </enterprise-beans>

 <interceptors>
   <interceptor>
    <interceptor-class>ClassInterceptor</interceptor-class>
    <post-activate>
      <class>InterceptorSuperClass</class>
	 <lifecycle-callback-method>interceptorSuperClassPostActivate</lifecycle-callback-method>
    </post-activate>
   </interceptor>
 </interceptors> 

 <assembly-descriptor>
   <interceptor-binding>
     <ejb-name>TestBean</ejb-name>
     <interceptor-class>ClassInterceptor</interceptor-class>
   </interceptor-binding>
 </assembly-descriptor>

您可以声明适用于模块中所有会话和消息驱动的 Bean 的缺省拦截器。缺省拦截器只能在部署描述符中声明,并且缺省拦截器是通过 ejb-name 为“*”来指定的。使用以下示例来声明缺省拦截器。

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>*</ejb-name>
      <interceptor-class>DefaultInterceptor</interceptor-class>
    </interceptor-binding>
  </assembly-descriptor>

您可以通过在 XML 中使用 ExcludeDefaultInterceptors 注释或 exclude-default-interceptors 元素以从特定类或方法中排除缺省拦截器。使用以下示例来排除缺省拦截器(使用注释):

@ExcludeDefaultInterceptors
public class TestBean { /* ... */ }

public class TestBean2 {
	@ExcludeDefaultInterceptors
	public void businessMethod() { /* ... */ }
}

使用以下示例来排除缺省拦截器(使用部署描述符):

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <exclude-default-interceptors>true</exclude-default-interceptors>
    </interceptor-binding>

    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <exclude-default-interceptors>true</exclude-default-interceptors>
           <method>
        <method-name>businessMethod</method-name>
           </method>
    </interceptor-binding>
  </assembly-descriptor>

在对某种方法调用拦截器时,将首先调用缺省拦截器类,其次调用类级别拦截器,最后调用来自 EJB 类中的拦截器方法。对于单个拦截器类层次结构,将始终首先在最常规的超类上调用拦截器方法。缺省和类级别拦截器类将按照部署描述符或拦截器注释中指定的顺序来调用。您可以通过在部署描述的 interceptor-order 元素中指定缺省和类级别拦截器的完整列表来覆盖此顺序。

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <!--
        The default ordering would be:
	  1. DefaultInterceptor
	  2. ClassInterceptor1
	  3. ClassInterceptor2

	The following stanza overrides the default ordering.
      -->
      <interceptor-order>
        <interceptor-class>ClassInterceptor2</interceptor-class>
	<interceptor-class>DefaultInterceptor</interceptor-class>
	<interceptor-class>ClassInterceptor1</interceptor-class>
      </interceptor-order>
    </interceptor-binding>
  </assembly-descriptor>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值