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 用于附加实现)
添加回答
举报