4 回答

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您可能會使用來自您的業務領域的更多不言自明的名稱來代替。

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

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

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 用于附加實現)
添加回答
舉報