You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:24:19