Quarkus生产者方法无日志、无法调试及Bean注入异常问题咨询
问题分析与解答
问题现象
DocumentCreatorFactory中的生产者方法getSomeBeans无控制台日志输出,也无法调试SomeBeanService中直接注入的Instance<SomeBean>找不到任何Bean,但通过@Any修饰的Instance配合限定符筛选后能找到对应Bean
相关代码片段
生产者类
@ApplicationScoped @JBossLog public class DocumentCreatorFactory { @Produces @ApplicationScoped public List<SomeBean> getSomeBeans(@Any Instance<SomeBean> someBeans) { log.infof("######### Producer started: %d #########", documentCreators.stream().count()); return someBeans.select( TagContext.Literal.of(Tag.CORE, Tag.CH) ).stream().toList(); } }
限定符注解定义
@Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) public @interface TagContext { Tag[] value() default {Tag.CORE}; final class Literal extends AnnotationLiteral<TagContext> implements TagContext { private final Tag[] value; public static Literal of(Tag... value) { return new Literal(value); } private Literal(Tag... value) { this.value = value; } @Override public Tag[] value() { return value; } } }
Bean实现类
@TagContext({Tag.CORE, Tag.CH}) @ApplicationScoped @JBossLog public class TagCoreAndChService implements SomeBean { @Override public void create() { log.infof("Core And Ch Some Bean Create"); } } @TagContext @ApplicationScoped @JBossLog public class TagCoreService implements SomeBean { @Override public void create() { log.infof("Core And Ch Some Bean Create"); } }
Bean使用类
@ApplicationScoped @JBossLog public class SomeBeanService { @Inject Instance<SomeBean> someBeans; @Inject @Any Instance<SomeBean> allSomeBeans; public void someProcessing(String inParam) { // 检查计数时未找到任何Bean log.infof("Num of beans: %d", someBeans.stream().count()); Instance<DocumentCreator> core = allSomeBeans.select( Literal.of(Tag.CORE, Tag.CH) ); // 在此处操作后能找到部分Bean log.infof("Num of beans AFTER: %d", core.stream().count()); } }
原因分析
1. 生产者方法未执行的原因
- CDI生产者方法仅在被生产的类型被注入时才会触发执行:当前代码中没有任何地方注入
List<SomeBean>,所以getSomeBeans方法根本不会被调用,自然看不到日志也无法调试。 - 代码存在变量名错误:方法内使用了未定义的
documentCreators变量,实际参数名是someBeans,就算方法执行也会抛出空指针异常。
2. 直接注入的Instance<SomeBean>找不到Bean的原因
- 直接注入
Instance<SomeBean>时,CDI会默认查找不带任何限定符的SomeBean实例,但你的两个SomeBean实现类都带有@TagContext限定符,不符合无限定符的查找条件,因此找不到Bean。 @Any修饰的Instance会匹配所有SomeBean类型的Bean(无论是否带限定符),之后通过select(TagContext.Literal.of(Tag.CORE, Tag.CH))筛选,能匹配到TagCoreAndChService,所以能找到对应Bean。
解决建议
触发生产者方法执行:在需要使用筛选后Bean列表的类中注入
List<SomeBean>,比如在SomeBeanService中添加:@Inject List<SomeBean> filteredSomeBeans;同时修正生产者方法中的变量名错误,将
documentCreators改为someBeans。让直接注入的
Instance<SomeBean>找到目标Bean:给注入点添加对应限定符,比如:// 匹配所有带@TagContext的Bean @Inject @TagContext Instance<SomeBean> someBeans;或者匹配特定Tag组合:
@Inject @TagContext({Tag.CORE, Tag.CH}) Instance<SomeBean> someBeans;
内容的提问来源于stack exchange,提问作者joe_specimen
相关产品推荐
相关产品推荐

