【问题标题】:Is interceptor really disabled by default?拦截器真的默认禁用了吗?
【发布时间】:2013-10-22 20:19:09
【问题描述】:

我今天遇到了这种困惑。 Quote from Weld's documentation (right under Section 9.3),

默认情况下,所有拦截器都被禁用。我们需要启用我们的 拦截器。我们可以使用 bean 的 beans.xml 描述符来做到这一点 档案。但是,此激活仅适用于其中的 bean 存档。

但是,在我目前正在进行的项目中,我有一个用于分析方法的拦截器。我的META-INF/beans.xml基本上是空的:

<?xml version="1.0" encoding="UTF-8"?>
<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_1_1.xsd"
       version="1.1" bean-discovery-mode="all">
</beans>

但我仍然从该分析拦截器获得预期的日志。那么,正如标题所说,拦截器真的默认禁用了吗?

顺便说一句,我在项目中使用 weld-se 来实现 CDI 功能,因为 CDI 是 Java EE 堆栈中项目唯一需要的东西。

更新

今天折腾了拦截器,发现如果用旧的@Interceptors来表示拦截实现类,beans.xml里面就不需要指定什么了。但是,如果您使用拦截器绑定,即使用@Interceptor 注释来指示拦截器类,则必须通过将拦截器类添加到beans.xml 来启用拦截。根据我的经验,CDI 1.1 仍然如此,如上面beans.xml 中的版本所示。顺便说一句,在这种情况下,我使用org.jboss.weld.se:weld-se:2.0.4.Final 来实现 CDI,我相信它实现了 CDI 1.1。

【问题讨论】:

  • 如果可以请链接到文档。您是否找到了 Weld 1.0 或 1.1 文档,但使用的是 Weld 2.0?
  • @JohnAment:好点。我没有注意到我的原始报价属于哪个版本的 Weld。无论如何,我更新了weld 2.1.0.Final 文档中的引用及其链接。
  • 好的,那么是的。我现在明白了。是的,当你使用@Interceptors 时,拦截器默认开启,因为你在被拦截对象和拦截器之间创建了紧密耦合,它最终会启用它。但是,正如文档中所指出的,@Interceptors 是由 Interceptor 规范提供的,而不是 EJB 或 CDI 规范,因此预计只会应用 Interceptor 规范的规则(您可能会发现其他规则也是如此,但它是不便携)。
  • @JBT 根据 Weld 1.x 为 JEE6 规范实施的 CDI 1.0。我确认你的发现。如果使用 @Interceptors(InterceptorClass.class),beans.xml 确实需要一个 Interceptors 标记,其中拦截器类名称作为值。如果您更喜欢注释方法(例如@MyLoggingInterceptor),那么必须在 beans.xml 中声明 com.myorg.LoggingIntercepttingClass。
  • 使用 @Priority 注释拦截器将启用它,而不包含 beans.xml。例如@Priority(Interceptor.Priority.APPLICATION)

标签: jakarta-ee cdi jboss-weld weld


【解决方案1】:

在他的 EDIT 中确认 JBT 的发现。根据 JEE6 规范的 Weld 1.0 实施的 JSR-299 的 CDI 规范 1.0。请参考我引用的this pointer

默认情况下,bean 存档没有通过拦截器绑定绑定的已启用拦截器。必须通过在&lt;interceptors&gt; 的子&lt;class&gt; 元素中列出完全限定的类名来显式启用拦截器。 如下面的方法 2 所示

举个例子:

第一个强制性步骤是拦截器绑定:

@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface Loggable {
}

第二个强制性步骤是拦截类:

@Interceptor
@Loggable
public class LoggingInterceptor {

    @AroundInvoke
    public Object logMethodEntry(InvocationContext ctx) throws Exception{
        System.out.println("In LoggingInterceptor..................... before method call");
        Object returnMe = ctx.proceed();
        System.out.println("In LoggingInterceptor..................... after method call");
        return returnMe;
    }
}

可以使用以下任一方法实现第三步

方法 1,一个空的 beans.xml 将完成这项工作

@Stateless
@Interceptors(LoggingInterceptor.class)     //class interception
public class Displayer implements DisplayerLocal {

    @Override
    //@Interceptors(LoggingInterceptor.class)  //method interception
    public void displayHi() {
        System.out.println(".....Hi there............");
    }
}

方法2,需要beans.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<beans 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/beans_1_0.xsd">
    <interceptors>
        <class>com.companyname.LoggingInterceptor</class>
    </interceptors>
</beans>

然后是截取的类:

@Stateless
@Loggable       //class interception
public class Displayer implements DisplayerLocal {

    @Override
    //@Loggable      //method interception
    public void displayHi() {
        System.out.println(".....Hi there............");
    }
}

【讨论】:

  • 我们将应用程序迁移到 Java 11 并且“方法 1 - 空 beans.xml”不再起作用(在 TomEE 和 Wildfly 上)。我们切换到方法 2,效果很好。
【解决方案2】:

1.1 版本默认启用拦截器和装饰器。请参阅新 CDI 规范的highlights

【讨论】:

  • 我不得不说我不同意你的回答。请参阅我的更新了解原因。
猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 2015-09-03
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多