Jakarta ee 为什么对同一个@Interceptor调用@Inject三次?

Jakarta ee 为什么对同一个@Interceptor调用@Inject三次?,jakarta-ee,cdi,interceptor,Jakarta Ee,Cdi,Interceptor,我试图了解拦截器是如何工作的,我对其生命周期有一个疑问 我的CacheableInterceptor有一个@Inject注释,用于获取记录器 Logger@Producer方法(类LoggerFactoryImpl)在同一个bean实例上被调用了3次(请参见日志跟踪) 这意味着对每个intercept*方法调用一次它(我试图删除interceptPreDestoy方法,并且调用了两次生产者) 我在拦截器规范中找不到这个东西。你能解释一下为什么吗?我是否在@Producer方法中出错 多谢各位 拦

我试图了解拦截器是如何工作的,我对其生命周期有一个疑问

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

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

这意味着对每个intercept*方法调用一次它(我试图删除interceptPreDestoy方法,并且调用了两次生产者)

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

多谢各位

拦截器生命周期

拦截器类与其关联的目标具有相同的生命周期 班级。创建目标类实例时,拦截器类 还为中每个声明的拦截器类创建实例 目标类。也就是说,如果目标类声明了多个 拦截器类,当 已创建目标类实例。目标类实例和所有 拦截器类实例在任何 @调用构造后回调,以及任何@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 {

}
CachableInterceptor拦截器的代码

@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;
    }

}

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

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

如果MyController的作用域为
@RequestScope
或除
@dependent
以外的任何日志生成器,请检查是否发生这种情况。是,如果
MyController
具有作用域
@RequestScoped
或除
@Dependent
之外的任何其他作用域,则会发生@RequestScopedCheck。是的,它会发生在@RequestScopedWell上,正如您从日志中看到的那样,实例是相同的(@207755267),但注入会按照每个方法井执行一次,正如您从日志中看到的一样,实例是相同的(@207755267),但每个方法执行一次注入