Spring boot - 在 @Qualifier 上使用可配置的值

use*_*666 5 java spring spring-boot

我有一个接口的两个实现,我想根据配置选择要使用的实现。限定符解决方案不起作用,因为它在配置之前已初始化。我怎样才能做到这一点?

Mar*_*nik 11

我有你的评论:

我有两个不同的作业实现,并且每个月都可以更改类型,因此如果可配置,则可以减少部署和代码更改。

你可能有这样的事情:

 interface Job {
     void foo();
 }

 class JobA implements Job {
     void foo() {...}
 }

 class JobB implements Job {
     void foo() {...}
 }

 class JobExecutor {
    
    Job job;
    // autowired constructor
    public JobExecutor(Job job) {this.job = job;}
 }
Run Code Online (Sandbox Code Playgroud)

而且,如果我没猜错的话,在同一个应用程序上下文中同时加载两个 bean 是没有意义的。

但如果是这样,那么@Qualifier就不是适合这项工作的工具。

我建议使用集成到 spring boot 中的条件:

@Configuration
public class MyConfiguration {

    @ConditionalOnProperty(name = "job.name", havingValue = "jobA")
    @Bean 
    public Job jobA() {
         return new JobA();
    }

    @ConditionalOnProperty(name = "job.name", havingValue = "jobB")
    @Bean 
    public Job jobB() {
         return new JobB();
    }
    @Bean
    public JobExecutor jobExecutor(Job job) {
       return new JobExecutor(job);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在application.properties(或任何你拥有的 yaml 中)定义:

 job.name = jobA # or jobB
Run Code Online (Sandbox Code Playgroud)

当然,jobA/jobB您可能会使用来自您的业务领域的更多不言自明的名称来代替。


use*_*666 1

我最终将两个自动装配的实现添加到主应用程序类中,然后为每个实现定义一个 bean:

@Autowired
TypeOneImpl typeOneImpl
@Bean(name = "typeOneImpl")
public InterfaceRClass getTypeOneImpl()
{
    return typeOneImpl;
}
Run Code Online (Sandbox Code Playgroud)

然后在另一个类中我定义了一个配置字段

@Value("${myClass.type}")
private String configClassType;
// the below should be defined in constructor
private final InterfaceRClass interfaceRClassElement ;
Run Code Online (Sandbox Code Playgroud)

并使用 @Autowired 注释为其添加了一个设置器:

@Autowired
public void setMyClassType(ApplicationContext context) {
    interfaceRClassElement = (InterfaceRClass) context.getBean(configClassType);
}
Run Code Online (Sandbox Code Playgroud)

在配置中,该值应该是typeOneImpl(添加typeTwoImpl是为了额外的实现)