InterceptorBinding不起作用

时间:2015-10-22 12:45:55

标签: java java-ee java-ee-6 interceptor websphere-8

我创建了一个自定义注释,如下所示

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

我写了一个拦截器,如下面的

@Traceable
@Interceptor
public class EnterExitLogger {
    @AroundInvoke
    public Object aroundInvoke(InvocatiobContext c) {}
}

拦截器和注释位于名为common-utils的模块中。

我在类级别使用@Traceable注释了我的目标类,如下所示

@Traceable
public class CDIManagedBean {
}

我在我的beans.xml文件中声明了拦截器条目,如下所示

<interceptors>
    <class>my.package.EnterExitLogger</class>
</interceptors>

目标类位于单独的模块中。 beans.xml位于目标类模块的META-INF目录中。

目标类的方法是从rest类调用的。当我调用方法时,不会调用拦截器的AroundInvoke方法。

我阅读了文档,并了解拦截器应该包含一个公共的无参数构造函数。我加了。但是拦截器还没有被调用。

在阅读文档后,我在自定义注释中添加了@Inherited。但是拦截器还没有被调用。

从文档中我注意到拦截器实现了Serializable接口。虽然没有提到我也实现了Serializable。仍然没有奏效。

然后我从拦截器,beans.xml文件和目标类中删除了自定义注释。我还从拦截器中删除了public no参数构造函数并删除了Serializable。

然后我用@Interceptors(EnterExitLogger.class)注释了目标类并调用了流程。我的拦截器被召唤了。

有谁能告诉我如何使用InterceptorBinding?

P.S。

我正在WAS 8.5服务器中部署我的耳朵。

2 个答案:

答案 0 :(得分:5)

Java EE Tutorial提供了一个很好的解释和一些关于拦截器的例子:

创建拦截器绑定注释,必须使用@Inherited@InterceptorBinding进行注释:

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

创建一个incerceptor类,该类使用上面创建的拦截器绑定注释以及@Interceptor注释进行注释。

每个@AroundInvoke方法都会使用InvocationContext参数,返回Object,并抛出Exception@AroundInvoke方法必须调用InvocationContext#proceed()方法,这会导致调用目标类方法:

@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {

    public LoggedInterceptor() {

    }

    @AroundInvoke
    public Object logMethodEntry(InvocationContext invocationContext) throws Exception {

        System.out.println("Entering method: "
                + invocationContext.getMethod().getName() + " in class "
                + invocationContext.getMethod().getDeclaringClass().getName());

        return invocationContext.proceed();
    }
}

一旦定义了拦截器和绑定类型,就可以使用绑定类型注释bean和单个方法,以指定在bean的所有方法或特定方法上调用拦截器。

例如,PaymentHandler bean带有注释@Logged,这意味着任何对其业务方法的调用都将导致调用拦截器的@AroundInvoke方法:

@Logged
@SessionScoped
public class PaymentHandler implements Serializable {...}

但是,您只能通过注释所需的方法来拦截bean的一组方法:

@Logged
public String pay() {...}

@Logged
public void reset() {...}

为了在CDI应用程序中调用拦截器,必须在beans.xml文件中指定它:

<interceptors>
    <class>your.package.LoggedInterceptor</class>
</interceptors>

如果应用程序使用多个拦截器,则会按beans.xml文件中指定的顺序调用拦截器。

答案 1 :(得分:1)

在保留拦截器的模块中添加空beans.xml文件后,问题得以解决。我想只有当我想使用cdi注入时才需要beans.xml文件。