首页 > 解决方案 > 尝试自动装配多个实现时无法从 Java 类中获取注释

问题描述

在 Java 11/Spring REST API 项目中,我有一个具有多个实现的接口。我想在配置中选择实现(在本例中为 application.yml 文件):


import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME)
@Target(TYPE)
public @interface PickableImplementation {
       // This id will match an entry in the config file
       public String id() default "";
}

所以我有两种可能的“可选”实现:

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.mycompany.api.util.PickableImplementation;

@Component
@Service
@PickableImplementation(id = "s3")
public class BatchProcessServiceS3 implements BatchProcessService {
        // Some implementation biz logic
}

// In another file, with the same imports:

@Component
@Service
@PickableImplementation(id = "azure")
public class BatchProcessServiceAzure implements BatchProcessService {
        // Another implementation biz logic
}

在这种情况下是控制器的消费者类中,我尝试选择所需的实现:

import com.mycompany.api.util.PickableImplementation;
import java.util.List;

@RestController
@RequestMapping("/batch")
public class BatchController {

    @Autowired private Environment env;
    private BatchProcessService batchProcessService;
    private final List<BatchProcessService> batchProcessImplementations;

    public BatchController(List<BatchProcessService> batchProcessImplementations,
                            Environment environment){
        this.env = environment;
        var activeSvcImplementationId = env.getRequiredProperty("buckets-config.active");
        this.batchProcessImplementations = batchProcessImplementations;
        
        for (var batchProcessService : this.batchProcessImplementations) {
                if(batchProcessService.getClass().isAnnotationPresent(PickableImplementation.class)) {
                        // Verify the id, compare with the one from config file, etc.
                }
        }
    }
}

预期行为:在循环中,我希望获取每个实现的注释,遍历列表,验证它是否与 application.yml 匹配,如果匹配,则选择它来填充服务层(私有 BatchProcessService batchProcessService) .

实际行为:不仅isAnnotationPresent()方法返回 false,而且如果我尝试getAnnotations()我得到一个空数组,就像类中没有注释一样。除了我的自定义注释之外,至少还有两个附加注释(组件、服务和其他与日志记录等相关的注释)。作为另一个令人费解的细节,如果我在调试会话的中间对类的限定名称运行getAnnotations() ,则存在注释。但是在那一刻,对列表中的元素运行该方法会返回 0 个注释。

我已经没有想法了,有没有人尝试过自动装配多个实现的相同组合,同时依赖自定义注释?

附加参考:

标签: javaspringdependency-injectionannotationsautowired

解决方案


推荐阅读