前言
今天升级了quarkus到最新版本1.8.0.final版本,然后就GG了,之前在ContainerRequestFilter注入的一个业务Bean就报错了,百度和Google 了半天没找到具体的解决方案,最后在一个不相干的论坛里找到了蛛丝马迹,然后解决了问题,所有这里记录下解决方案
出bug的代码
@Priority(Priorities.USER + 1)//值越大,优先级越小 @Provider public class RequestLogFilter implements ContainerRequestFilter { @Inject LogService logService; @Override public void filter(ContainerRequestContext requestContext) throws IOException { //保存请求日志 } }这是一段拦截器代码,用于统一拦截请求记录请求的日志信息,注入的对象是一个日志服务对象,日志服务对象中包含了访问数据库的JPA对象EntityManager实例,然后就报错了
异常信息
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解答中找到了灵感解决了问题。
解决方案
@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了