亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

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

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

喵喵時光機 2023-05-17 17:02:54
我有一個接口的兩個實現,我想根據配置選擇要使用的實現。限定符解決方案不起作用,因為它是在配置之前初始化的。我怎樣才能做到這一點?我收到了你的評論:我有兩個不同的作業實現,并且可以每月更改類型,因此如果可配置,則可以減少部署和代碼更改。你可能有這樣的事情: 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您可能會使用來自您的業務領域的更多不言自明的名稱來代替。
查看完整描述

4 回答

?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超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;}

?}

而且,如果我沒聽錯的話,在同一個應用程序上下文中同時加載兩個 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您可能會使用來自您的業務領域的更多不言自明的名稱來代替。


查看完整回答
反對 回復 2023-05-17
?
慕尼黑的夜晚無繁華

TA貢獻1864條經驗 獲得超6個贊

如果您稍微擺弄一下基于 Spring java 的配置,您可以使用它來完成它,您可以在其中根據配置值以編程方式決定正確的實現:


@Configuration

public 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


查看完整回答
反對 回復 2023-05-17
?
蝴蝶刀刀

TA貢獻1801條經驗 獲得超8個贊

假設您有一個界面:


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();

        }

    }


}


查看完整回答
反對 回復 2023-05-17
?
神不在的星期二

TA貢獻1963條經驗 獲得超6個贊

我最終將兩個自動裝配的實現添加到主應用程序類,然后為每個實現定義一個 bean:


@Autowired

TypeOneImpl typeOneImpl

@Bean(name = "typeOneImpl")

public InterfaceRClass getTypeOneImpl()

{

    return typeOneImpl;

}

然后在另一個類中我定義了一個配置字段


@Value("${myClass.type}")

private String configClassType;

// the below should be defined in constructor

private final InterfaceRClass interfaceRClassElement ;

并使用 @Autowired 注釋為其添加了一個 setter:


@Autowired

public void setMyClassType(ApplicationContext context) {

    interfaceRClassElement = (InterfaceRClass) context.getBean(configClassType);

}

在配置中,該值應為 typeOneImpl(添加 typeTwoImpl 用于附加實現)


查看完整回答
反對 回復 2023-05-17
  • 4 回答
  • 0 關注
  • 360 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號