如何解决为什么在单例中注入的 CDI 拦截器不被 Glassfish 5.1 容器调用
在日志文件中记录方法进入和退出的CDI拦截器没有被容器为单例类调用?
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD,TYPE})
public @interface Logit {
}
这里是拦截器:
@Interceptor
@Logit
public class RecordIntereceptor implements Serializable {
private static final long serialVersionUID = -2230122751970857900L;
public RecordIntereceptor() {
}
@AroundInvoke
public Object logEntryExit(InvocationContext ctx)throws Exception{
String methodName = ctx.getmethod().getName();
String declaringClass= ctx.getmethod().getDeclaringClass().getCanonicalName();
Logger logger = Logger.getLogger(declaringClass);
logger.entering("List Service Intereceptor "+declaringClass,methodName);
Object result = ctx.proceed();
logger.exiting("List Service Intereceptor "+declaringClass,methodName);
return result;
}
}
@Logit
@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DataLoaderSessionBean {
@postconstruct
public void createData() {
removeStartupData();
loadUsers();
loadParts();
}
...........
...........
}
最后是 beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
<interceptors>
<class>org.me.jsfproject.intereceptor.RecordIntereceptor</class>
</interceptors>
</beans>
日志文件中没有方法“DataLoaderSessionBean.createData()”的方法进入或退出日志。使用调试器,我单步执行代码并且容器没有调用拦截器。虽然拦截器对非单例类工作正常?知道为什么会这样。
更新 1
具有生命周期方法(即@postconstruct)的拦截器似乎有限制,它们必须是@Target({TYPE}) 所以我创建了一个额外的新拦截器接口和一个新的拦截器,仅用于单例类,如下所示:@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({TYPE})
public @interface LifeCycleLogger {
}
@Interceptor
@LifeCycleLogger
public class LifeCycleIntereceptor implements Serializable {
private static final long serialVersionUID = -2230122753370857601L;
public LifeCycleIntereceptor() {
}
@postconstruct
public void logpostconstruct(InvocationContext ctx){
String methodName = ctx.getmethod().getName();
String declaringClass= ctx.getmethod().getDeclaringClass().getCanonicalName();
Logger logger = Logger.getLogger(declaringClass);
logger.entering("Life Cycle Intereceptor "+declaringClass,methodName);
try {
ctx.proceed();
} catch (Exception e) {
logger.log(Level.SEVERE,"LifeCycle Interceptor Post Construct caught an exception: {0}",e.getMessage());
}
logger.exiting("Life Cycle Intereceptor "+declaringClass,methodName);
}
}
我改变了单例如下:
@LifeCycleLogger
@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DataLoaderSessionBean{
................
public DataLoaderSessionBean(){
}
@postconstruct
public void createData() {
........
}
............
}
谢谢
?解决方法
由于 createData()
是 DataLoaderSessionBean
的生命周期方法,它不会被 @AroundInvoke
注释捕获。
要在拦截器中声明捕获 @PostConstruct
生命周期调用的方法,您必须使用相同的注释对其进行注释:
@PostConstruct
public void logPostConstruct(InvocationContext ctx) throws Exception{
String methodName = ctx.getMethod().getName();
String declaringClass= ctx.getMethod().getDeclaringClass().getCanonicalName();
Logger logger = Logger.getLogger(declaringClass);
logger.entering("List Service Intereceptor "+declaringClass,methodName);
ctx.proceed();
logger.exiting("List Service Intereceptor "+declaringClass,methodName);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。