最近,我正在开发一个为客户端代码提供ServiceA
的spring boot starter。我想提供配置属性:
my.namespace.serviceA=impl1 #or other implemtations
my.namespace.serviceA.impl1.prop1=ServiceAImpl1Prop1Val
my.namespace.serviceA.impl1.prop2=ServiceAImpl1Prop2Val
# some other properties of ServiceA
我还为@ConfigurationProperties
的不同实现添加了几个注释为ServiceA
的Bean类,因为springboot会自动将这些属性加载到这些bean中。
我的初学者希望为客户端代码提供ServiceA
的接口,以便它可以用作:
@Autowire
private ServiceA serviceA;
我需要提供一个工厂方法,如:
@Bean
public ServiceA serviceA() {
//TODO load my.namespace.serviceA and create the corresponding
//instance of ServiceA Implementation with given properties
}
由于属性根据不同的实现而变化,是否有一种优雅的方法来实现这种工厂方法利用@ConfigurationProperties
的属性bean?
答案 0 :(得分:3)
从表面上看,你的答案是90%。
您可以将ServiceA标记为组件,而不是手动创建bean,而Spring组件扫描将为您创建bean。
查看ServiceA的实现
@ConfigurationProperties(prefix = "my.namespace.serviceA.impl1")
@Component
public ConcreteA implements ServiceA {
private String prop1;
private String prop2;
}
根据您想要一个ServiceA实例的事实,您仍然需要使用@ConfigurationProperties
为您的班级添加注释,但请移除@Component
。
@ConfigurationProperties(prefix = "my.namespace.serviceA.impl1")
public ConcreteA implements ServiceA {
private String prop1;
public void setProp1(String s) {
prop1 = s;
}
}
您必须至少拥有属性的设置者。
然后在你创建bean的config类中
@ConfigurationProperties(prefix = "my.namespace")
@Configuration
public SomeConfig {
private String serviceA;
public void setServiceA(String s) {
serviceA = s;
}
@Bean
public ServiceA serviceA() {
if (serviceA.equals("ConcreteA1")) {
return new ConcreteA1();
} else {
return new ConcreteA2();
}
}
}
使用if语句的方法实际上违反了开放/封闭原则,内省是一种更好的方法,但我认为你明白了。