如何在Quarkus中通过ArC获取带自定义注解的Bean?
在Quarkus中通过自定义限定注解简洁获取Bean实例
问题场景
需要在运行时根据用户输入动态查找带有自定义限定注解的Bean,目前采用手动实现注解接口的方式可以实现功能,但代码繁琐,希望找到更简洁的方案。
现有工作代码
InstanceHandle<Service> instanceHandleA = Arc.container() .instance(Service.class, new SupportsJobTypeImpl(JobType.A)); InstanceHandle<Service> instanceHandleB = Arc.container() .instance(Service.class, new SupportsJobTypeImpl(JobType.B)); class SupportsJobTypeImpl implements SupportsJobType { JobType requestedJobType; public SupportsJobTypeImpl(JobType requestedJobType) { this.requestedJobType = requestedJobType; } @Override public JobType value() { return requestedJobType; } @Override public Class<? extends Annotation> annotationType() { return SupportsJobType.class; } }
相关背景代码
public enum JobType { A,B } @Qualifier @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface SupportsJobType { JobType value(); } @ApplicationScoped @SupportsJobType(JobType.A) public class ServiceForA extends Service { } @ApplicationScoped @SupportsJobType(JobType.B) public class ServiceForB extends Service { }
无效的尝试方案
尝试使用AnnotationLiteral简化实现,但两种写法均无法匹配到目标Bean:
方案1:抽象内部类实现
@Qualifier @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface SupportsJobType { JobType value(); public abstract class Literal extends AnnotationLiteral<SupportsJobType> implements SupportsJobType { JobType requestedJobType; public Literal() { } @Override public JobType value() { return requestedJobType; } @Override public Class<? extends Annotation> annotationType() { return SupportsJobType.class; } } }
调用代码:
InstanceHandle<Service> instanceHandleA = Arc.container().instance(Service.class, new SupportsJobType.Literal() { public JobType value() { return JobType.A; } });
方案2:带构造方法的内部类
@Qualifier @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface SupportsJobType { JobType value(); class Literal extends AnnotationLiteral<SupportsJobType> implements SupportsJobType { JobType requestedJobType; public Literal(JobType requestedJobType) { this.requestedJobType = requestedJobType; } @Override public JobType value() { return requestedJobType; } @Override public Class<? extends Annotation> annotationType() { return SupportsJobType.class; } } }
调用代码:
InstanceHandle<Service> instanceHandleA = Arc.container().instance(Service.class, new SupportsJobType.Literal(JobType.A));
正确的简化实现方式
问题核心在于AnnotationLiteral需要保证注解实例的属性不可变且equals/hashCode符合CDI规范,以下是正确的实现:
修正后的SupportsJobType注解
@Qualifier @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface SupportsJobType { JobType value(); class Literal extends AnnotationLiteral<SupportsJobType> implements SupportsJobType { private final JobType value; private Literal(JobType value) { this.value = value; } // 静态工厂方法简化实例创建 public static Literal of(JobType value) { return new Literal(value); } @Override public JobType value() { return value; } } }
调用方式
// 获取JobType.A对应的Bean InstanceHandle<Service> instanceHandleA = Arc.container() .instance(Service.class, SupportsJobType.Literal.of(JobType.A)); // 获取JobType.B对应的Bean InstanceHandle<Service> instanceHandleB = Arc.container() .instance(Service.class, SupportsJobType.Literal.of(JobType.B));
替代方案:使用Arc.select()
也可以直接通过Arc.container().select()方法进行查找,代码更简洁:
Instance<Service> serviceAInstance = Arc.container() .select(Service.class, SupportsJobType.Literal.of(JobType.A)); Service serviceA = serviceAInstance.get();
为什么之前的写法失败?
AnnotationLiteral已经默认实现了符合CDI规范的equals和hashCode方法,但需要确保注解的属性是不可变的final字段。之前的实现中,属性未被声明为final,或者初始化逻辑存在问题,导致注解实例的属性值无法被正确匹配,最终无法找到对应的Bean。
内容的提问来源于stack exchange,提问作者syr
相关产品推荐
相关产品推荐

