【发布时间】:2016-04-12 23:09:23
【问题描述】:
我正在尝试了解拦截器的工作原理,但我有一个关于生命周期的问题。
我的 CacheableInterceptor 有一个 @Inject 注解,用于获取记录器。
Logger @Producer 方法(LoggerFactoryImpl 类)在同一个 bean 实例上被调用 3 次(参见日志跟踪)。
这意味着每个intercept*方法都会调用一次(我试图删除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