我试图了解拦截器是如何工作的,我对生命周期有疑问。
我的CacheableInterceptor有一个@Inject注释,用于获取记录器。
在同一个bean实例上调用Logger @Producer方法(类LoggerFactoryImpl)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;
}
}
答案 0 :(得分:0)
与CDI一起使用时的拦截器是依赖范围的bean。这意味着为每次调用创建了一个新的拦截器实例。此外,您的日志生成器也是依赖的,因此您也可以为每个日志生成器获取一个新的记录器。