猿问

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

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


我收到了你的评论:


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


你可能有这样的事情:


 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;}

 }

而且,如果我没听错的话,在同一个应用程序上下文中同时加载两个 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);

    }

}

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


 job.name = jobA # or jobB

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


喵喵时光机
浏览 295回答 4
4回答

慕盖茨4494581

我有两个不同的作业实现,并且可以每月更改类型,因此如果可配置,则可以减少部署和代码更改。你可能有这样的事情: 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;} }而且,如果我没听错的话,在同一个应用程序上下文中同时加载两个 bean 是没有意义的。但如果是这样,则@Qualifier不是适合这项工作的工具。我建议改用集成到 spring boot 中的条件:@Configurationpublic 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);    }}现在在application.properties(或任何你拥有的 yaml)中定义: job.name = jobA # or jobB当然,jobA/jobB您可能会使用来自您的业务领域的更多不言自明的名称来代替。

慕尼黑的夜晚无繁华

如果您稍微摆弄一下基于 Spring java 的配置,您可以使用它来完成它,您可以在其中根据配置值以编程方式决定正确的实现:@Configurationpublic class MyAppContext implements EnvironmentAware{    private Environment env;    @Override    public void setEnvironment(final Environment env) {       this.env = env;    }    @Bean    public MyBeanByConfig myBeanByConfig(){        String configValue = env.getProperty("mybean.config");        if(configValue.equals("1")){           return new MyBeanByConfigOne();        }else{           return new MyBeanByConfigTwo();        }    }}在限定符上你会放:@Qualifier("myBeanByConfig")您可能还需要在配置类上添加@ComponentScan和。@PropertySource

蝴蝶刀刀

假设您有一个界面:public interface Foo {    void doSomething();}和2个实现:public class Foo_A implements Foo {    @Override    doSomething() {...}}public class Foo_B implements Foo {    @Override    doSomething() {...}}现在您想根据属性文件中的属性值使用 Foo_A/Foo_B:foo_name: "A"我发现最简单的方法是:首先,您限定您的实施@Component("Foo_A")public class Foo_A implements Foo {    @Override    doSomething() {...}}@Component("Foo_B")public class Foo_B implements Foo {    @Override    doSomething() {...}}然后,无论您要在何处使用它(例如 Bar 类),您都可以只使用 @Qualifier 来指定您正在实例化的实现并使用 @Value 从属性中获取值。然后,在方法内部,通过一个简单的 if/else 语句,您可以使用属性值来决定要调用哪个实现。public class Bar {    @Value("${foo_name}")    private String fooName;    @Qualifier("Foo_A")    private Foo fooA;    @Qualifier("Foo_B")    private Foo fooB;    public void doSomething() {        if (fooName.equals("A")) {            fooA.doSomething();        } else {            fooB.doSomething();        }    }}

神不在的星期二

我最终将两个自动装配的实现添加到主应用程序类,然后为每个实现定义一个 bean:@AutowiredTypeOneImpl typeOneImpl@Bean(name = "typeOneImpl")public InterfaceRClass getTypeOneImpl(){    return typeOneImpl;}然后在另一个类中我定义了一个配置字段@Value("${myClass.type}")private String configClassType;// the below should be defined in constructorprivate final InterfaceRClass interfaceRClassElement ;并使用 @Autowired 注释为其添加了一个 setter:@Autowiredpublic void setMyClassType(ApplicationContext context) {    interfaceRClassElement = (InterfaceRClass) context.getBean(configClassType);}在配置中,该值应为 typeOneImpl(添加 typeTwoImpl 用于附加实现)
随时随地看视频慕课网APP

相关分类

Java
我要回答