前言
今天升级了quarkus到最新版本1.8.0.final版本,然后就GG了,之前在ContainerRequestFilter注入的一个业务Bean就报错了,百度和Google 了半天没找到具体的解决方案,最后在一个不相干的论坛里找到了蛛丝马迹,然后解决了问题,所有这里记录下解决方案
出bug的代码
代码语言:javascript复制@Priority(Priorities.USER 1)//值越大,优先级越小
@Provider
public class RequestLogFilter implements ContainerRequestFilter {
@Inject
LogService logService;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
//保存请求日志
}
}
这是一段拦截器代码,用于统一拦截请求记录请求的日志信息,注入的对象是一个日志服务对象,日志服务对象中包含了访问数据库的JPA对象EntityManager实例,然后就报错了
异常信息
代码语言:javascript复制Caused by: java.lang.RuntimeException: Error injecting cn.keking.project.capital.thirdparty.repository.AppLogRepository cn.keking.project.capital.thirdparty.service.LogService.logRepository
at cn.keking.project.capital.thirdparty.service.LogService_Bean.create(LogService_Bean.zig:166)
at cn.keking.project.capital.thirdparty.service.LogService_Bean.get(LogService_Bean.zig:204)
at cn.keking.project.capital.thirdparty.service.LogService_Bean.get(LogService_Bean.zig:239)
at cn.keking.project.capital.thirdparty.filter.RequestLogFilter_Bean.create(RequestLogFilter_Bean.zig:331)
... 54 more
Caused by: javax.enterprise.inject.CreationException: Synthetic bean instance for javax.persistence.EntityManager not initialized yet: javax_persistence_EntityManager_3cb728d15a0a04006cc75d03f784feb2bba9a5fb
- a synthetic bean initialized during RUNTIME_INIT must not be accessed during STATIC_INIT
- RUNTIME_INIT build steps that require access to synthetic beans initialized during RUNTIME_INIT should consume the SyntheticBeansRuntimeInitBuildItem
at javax.persistence.EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.create(EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.zig:117)
at javax.persistence.EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.create(EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.zig:140)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext.access$000(AbstractSharedContext.java:14)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at javax.persistence.EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.get(EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.zig:172)
at javax.persistence.EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.get(EntityManager_9b922d59b548563a5d960515e5e44f2bd846ceab_Synthetic_Bean.zig:188)
at cn.keking.project.capital.thirdparty.repository.AppLogRepository_Bean.create(AppLogRepository_Bean.zig:170)
at cn.keking.project.capital.thirdparty.repository.AppLogRepository_Bean.get(AppLogRepository_Bean.zig:207)
at cn.keking.project.capital.thirdparty.repository.AppLogRepository_Bean.get(AppLogRepository_Bean.zig:242)
at cn.keking.project.capital.thirdparty.service.LogService_Bean.create(LogService_Bean.zig:149)
异常的message中已说明了,在实例化filter的时候,EntityManager对象还未初始化,所有注入失败了。如果用异常message搜解决方案肯定都是搜索到quarkus的CDI文档,quarkus的CDI文档中确实给出了解决方案,但是实施起来比较复杂,最终博主在一个stackoverflow解答中找到了灵感解决了问题。
解决方案
代码语言:javascript复制@Priority(Priorities.USER 1)//值越大,优先级越小
@Provider
public class RequestLogFilter implements ContainerRequestFilter {
@Inject
javax.inject.Provider<LogService> logService;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
LogService log = logService.get();
//保存请求日志
}
}
看到区别了吧,注入的对象被javax.inject.Provider<LogService>接口包装了下,如此抽象作用域,以便可以从包含作用域的实例中查找范围较小的实例。使用的时候直接get()实例就可以获取到真实的业务Bean了