我创建了一个自定义注释,如下所示
@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服务器中部署我的耳朵。
答案 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文件。