【问题标题】:Why is @Inject called 3 times for the same @Interceptor?为什么@Inject 会为同一个@Interceptor 调用3 次?
【发布时间】:2016-04-12 23:09:23
【问题描述】:

我正在尝试了解拦截器的工作原理,但我有一个关于生命周期的问题。

我的 CacheableInterceptor 有一个 @Inject 注解,用于获取记录器。

Logger @Producer 方法(LoggerFactoryImpl 类)在同一个 bean 实例上被调用 3 次(参见日志跟踪)。

这意味着每个in​​tercept*方法都会调用一次(我试图删除interceptPreDestoy方法,并且生产者被调用了两次)。

我在拦截器规范中找不到这个东西。你能解释一下为什么吗?我在@Producer 方法中做错了吗?

谢谢

拦截器生命周期

拦截器类与其关联的目标具有相同的生命周期 班级。当一个目标类实例被创建时,一个拦截器类 还为每个声明的拦截器类创建实例 目标类。也就是说,如果目标类声明了多个 拦截器类,每个类的一个实例被创建时 创建目标类实例。目标类实例和所有 拦截器类实例在任何之前完全实例化 调用 @PostConstruct 回调,以及任何 @PreDestroy 回调 在目标类和拦截器类实例之前调用 被销毁了。

日志文件

[1/8/16 10:44:40:379 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger calling @Produces for injection point: [BackedAnnotatedField] @Inject protected it.tecla.utils.cache.CacheableInterceptor.logger, real bean: org.jboss.weld.bean.InterceptorImpl@2,077,555,267
[1/8/16 10:44:40:379 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger logger name from bean class
[1/8/16 10:44:40:379 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger name: it.tecla.utils.cache.CacheableInterceptor
[1/8/16 10:44:40:379 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 getLogger obtaining logger with name: it.tecla.utils.cache.CacheableInterceptor
[1/8/16 10:44:40:379 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger calling @Produces for injection point: [BackedAnnotatedField] @Inject protected it.tecla.utils.cache.CacheableInterceptor.logger, real bean: org.jboss.weld.bean.InterceptorImpl@2,077,555,267
[1/8/16 10:44:40:379 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger logger name from bean class
[1/8/16 10:44:40:380 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger name: it.tecla.utils.cache.CacheableInterceptor
[1/8/16 10:44:40:380 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 getLogger obtaining logger with name: it.tecla.utils.cache.CacheableInterceptor
[1/8/16 10:44:40:380 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger calling @Produces for injection point: [BackedAnnotatedField] @Inject protected it.tecla.utils.cache.CacheableInterceptor.logger, real bean: org.jboss.weld.bean.InterceptorImpl@2,077,555,267
[1/8/16 10:44:40:380 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger logger name from bean class
[1/8/16 10:44:40:380 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 produceLogger name: it.tecla.utils.cache.CacheableInterceptor
[1/8/16 10:44:40:380 CET] 00000242 id=         it.tecla.utils.logging.impl.LoggerFactoryImpl                1 getLogger obtaining logger with name: it.tecla.utils.cache.CacheableInterceptor

可缓存注释的代码

@Inherited
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Cacheable {

}

CacheableInterceptor 拦截器的代码

@Interceptor
@Cacheable
public class CacheableInterceptor {

    @Inject
    protected Logger logger;

    @PostConstruct
    protected void interceptPostConstruct(InvocationContext invocationContext) {
        System.out.println("post construct");
    }

    @AroundInvoke
    protected Object interceptAroundInvoke(InvocationContext invocationContext) throws Exception {

        System.out.println("intercepted");

        return invocationContext.proceed();

    }

    @PreDestroy
    protected void interceptPreDestroy(InvocationContext invocationContext) {
        System.out.println("pre destroy");
    }

}

MyController 类的代码

@Cacheable
public class MyController {

    @Inject
    protected Logger logger;

    public String add(@NotNull String a, @NotNull String b) {

        logger.logp(Level.FINE, logger.getName(), "add", "a={0}", a);
        logger.logp(Level.FINE, logger.getName(), "add", "b={0}", b);

        BigDecimal bdA = new BigDecimal(a);
        BigDecimal bdB = new BigDecimal(b);
        BigDecimal result = bdA.add(bdB);

        return result.toString();
    }

}

LoggerFactoryImpl 类的代码

public class LoggerFactoryImpl implements LoggerFactory {

    protected Logger logger = Logger.getLogger(this.getClass().getName());

    @Produces
    protected Logger produceLogger(InjectionPoint injectionPoint) {

        logger.logp(Level.FINE, logger.getName(), "produceLogger", "calling @Produces for injection point: {0}, real bean: {1}@{2}", new Object[] { injectionPoint, injectionPoint.getBean().getClass().getName(), System.identityHashCode(injectionPoint.getBean()) });

        LoggerConfig loggerConfig = injectionPoint.getAnnotated().getAnnotation(LoggerConfig.class);

        String name = null;
        if (loggerConfig != null) {
            logger.logp(Level.FINE, logger.getName(), "produceLogger", "logger name from annotation @LoggerConfig");
            name = loggerConfig.name();
        }

        if (name == null) {
            logger.logp(Level.FINE, logger.getName(), "produceLogger", "logger name from bean class");
            name = injectionPoint.getBean().getBeanClass().getName();
        }

        logger.logp(Level.FINE, logger.getName(), "produceLogger", "name: {0}", name);

        return this.getLogger(name);
    }

    @Override
    public Logger getLogger(String name) {

        logger.logp(Level.FINE, logger.getName(), "getLogger", "obtaining logger with name: {0}", name);

        Logger logger = Logger.getLogger(name);
        return logger;
    }

}

【问题讨论】:

  • 检查如果MyController 具有@RequestScoped@Dependent 以外的任何范围,是否会发生这种情况。
  • 是的,@RequestScoped 会发生这种情况

标签: jakarta-ee cdi interceptor


【解决方案1】:

与 CDI 一起使用时的拦截器是依赖范围的 bean。这意味着每次调用都会创建一个新的拦截器实例。此外,您的日志生成器也是依赖的,因此您也会为每个生成器获取一个新的记录器。

【讨论】:

  • 嗯,从日志中可以看出,实例是相同的 (@2,077,555,267),但每个方法执行一次注入
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-10
相关资源
最近更新 更多