CDI:跨不同模块/ bean归档使用拦截器 [英] CDI: Using Interceptors across different modules / bean archives

查看:175
本文介绍了CDI:跨不同模块/ bean归档使用拦截器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Java EE 6应用程序包含一个war和ejb模块,这些模块打包在ear文件中。我正在使用CDI进行DI(即我在两个模块中都有一个beans.xml文件)。我想使用war模块中的ejb模块中定义的日志拦截器。我在ejb的beans.xml中启用了拦截器:

My Java EE 6 application consists of a war and an ejb module packaged in ear file. I'm using CDI for DI (i.e. I have a beans.xml file in both modules). I want to use a logging interceptor that is defined in the ejb module in the war module, as well. I've enabled the interceptor in the ejb's beans.xml:

<beans>
    <interceptors>
        <class>com.test.interceptor.LoggingInterceptor</class>
    </interceptors>
</beans>

这仅适用于使用 ejb模块中的拦截器注释的类/ strong>即可。战争模块中的类不被截获(尽管它们也被拦截器注释)。我认为解决方案是在战争的拦截器中启用拦截器(如上所述)。但是无法使用以下消息部署应用程序:

This is working only for the classes that are annotated with the interceptor in the ejb module. Classes in war module are not intercepted (although they're annotated with the interceptor too). I thought the solution would be to enable the interceptor in the war's interceptor, as well (like above). But the application cannot be deployed with the following message:

SEVERE:加载应用程序时出现异常:WELD-001417启用拦截器类类com.test.interceptor.LoggingInterceptor既不是带注释的@Interceptor也没有通过便携式扩展注册

SEVERE: Exception while loading the app : WELD-001417 Enabled interceptor class class com.test.interceptor.LoggingInterceptor is neither annotated @Interceptor nor registered through a portable extension

我的LoggingInterceptor看起来像这样:

My LoggingInterceptor looks like this:

@Log
@Interceptor
public class LoggingInterceptor {
    private static final Logger logger =  Logger.getLogger(LoggingInterceptor.class.getName());

    static {
        logger.setLevel(Level.ALL);
    }

    @AroundInvoke
    public Object logMethod(InvocationContext ctx) throws Exception {
        logger.log(Level.FINE, "ENTRY {0} {1}",
                new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() });
        long startTime = System.nanoTime();
        try {
            return ctx.proceed();
        } finally {
            long diffTime = System.nanoTime() - startTime;
            logger.log(Level.FINE, "RETURN {0} {1}",
                new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() });
            logger.log(Level.FINE, "{0} took {1} ms", new Object[]{ ctx.getMethod(),
                    TimeUnit.MILLISECONDS.convert(diffTime, TimeUnit.NANOSECONDS)});
        }
    }

}

拦截器绑定:

@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Log {}

我如何使用两个模块的拦截器?

How can I use the interceptor for both modules?

推荐答案

J2EE 7规范说(参考):

J2EE 7 specification says (reference):


拦截器您在beans.xml文件中指定的内容仅适用于同一归档中的
类。使用@Priority注释为包含多个
模块的应用程序全局指定
拦截器

The interceptors that you specify in the beans.xml file apply only to classes in the same archive. Use the @Priority annotation to specify interceptors globally for an application that consists of multiple modules

此解决方案具有独立于供应商的优势。

This solution has the advantage of being vendor independent.

示例:

@Logged
@Interceptor
@Priority(Interceptor.Priority.APPLICATION)
public class LoggedInterceptor implements Serializable { ... }

这篇关于CDI:跨不同模块/ bean归档使用拦截器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆