7.11. 拦截器

拦截器允许您在 Bean 的业务方法中添加功能,而无需直接修改 bean 的方法。拦截器在 Bean 的任何业务方法之前执行。拦截器定义为 Jakarta Enterprise Beans 规范的一部分。

通过允许您使用注解将拦截器绑定到 bean,上下文和依赖注入功能增强了此功能。

拦截点

  • 业务方法拦截器:商业方法拦截器适用于 Bean 的客户调用 Bean 方法。
  • 生命周期回调拦截器:生命周期回调拦截器适用于容器调用的生命周期回调。
  • 超时方法拦截器:超时方法拦截器应用于容器调用企业 Java Bean 超时方法。

启用 Interceptors

默认情况下,禁用所有拦截器。您可以使用 bean 存档的 beans.xml 描述符启用拦截器。但是,此激活仅适用于该存档中的 bean。从 CDI 1.1 开始,可以使用 @Priority 注释为整个应用启用拦截器。

示例:在 beans.xml中启用 Interceptors

<beans
   xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://xmlns.jcp.org/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/beans_2.0.xsd">
   <interceptors>
      <class>org.mycompany.myapp.TransactionInterceptor</class>
   </interceptors>
</beans>

使 XML 声明解决了两个问题:

  • 它可让您在系统中指定拦截器的排序,以确保确定行为。
  • 它可让您在部署时启用或禁用拦截器类。

在使用 beans.xml 文件启用拦截器之前,使用 @Priority 启用的拦截器会被调用。

注意

@Priority 启用拦截器并且同时被 beans.xml 文件调用会导致无法移植的行为。因此,应避免这种启用组合,以便在不同的上下文和依赖注入实施之间保持一致的行为。

7.11.1. 将 Interceptors 与上下文和依赖注入一起使用

上下文和依赖注入可简化拦截器代码,更轻松地应用于您的业务代码。

如果没有上下文和依赖注入,拦截器有两个问题:

  • Bean 必须直接指定拦截器实施。
  • 应用程序中的每个 bean 都必须以正确的顺序指定完整的拦截器集合。这使得在应用程序范围内添加或移除拦截器会非常耗时且容易出错。
将 Interceptors 与上下文和依赖注入一起使用
  1. 定义拦截器绑定类型。

    @InterceptorBinding
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    public @interface Secure {}
  2. 标记拦截器实施。

    @Secure
    @Interceptor
    public class SecurityInterceptor {
      @AroundInvoke
      public Object aroundInvoke(InvocationContext ctx) throws Exception {
        // enforce security ...
        return ctx.proceed();
        }
    }
  3. 在您的开发环境中使用拦截器。

    @Secure
    public class AccountManager {
      public boolean transfer(Account a, Account b) {
        ...
      }
    }
  4. 通过将其添加到 META-INF/beans.xml 或 WEB-INF/beans.xml 文件,在部署中启用拦截器。

    <beans>
      <interceptors>
        <class>com.acme.SecurityInterceptor</class>
        <class>com.acme.TransactionInterceptor</class>
      </interceptors>
    </beans>

拦截器按照列出的顺序应用。