我有一个抽象类,其中包含一些使用@Value 设置的配置属性值。我想重用抽象类,但使用另一组配置属性。问题是,这些属性值已经在抽象类中设置了,所有的具体类都继承了它。
我想过:
在抽象类中创建另一组配置值,但这似乎会创建重复项,但是当将来还有第三组配置值时,这不是很可扩展。
将抽象类中配置值的可访问性从私有更改为受保护,并让具体类覆盖它。但我不确定这种覆盖是否好,因为它似乎对实际配置值是什么造成了混淆。
创建另一个类似于“AbstractService”的抽象类,但使用@Value 注入不同的配置值集。这似乎也造成了重复。
public abstract class AbstractService {
@Value("${config1}")
private String config1;
@Value("${config2}")
private String config2;
public void serviceMethod() {
//using config1 and config 2 values
}
}
public class concreteServiceA extends AbstractService {
public void serviceA() {
// using serviceMethod in the abstract class
}
}
public class concreteServiceB extends AbstractService {
public void serviceB() {
// using serviceMethod in the abstract class
}
}
如果在抽象类中使用构造函数传递所需参数,并让具体类使用构造函数注入和@Value来设置这些值,这是不是一个好方法?但如果有很长的配置值列表,这可能无法很好地扩展。
public abstract class AbstractService {
private String config1;
private String config2;
public AbstractService(String config1, String config2) {
this.config1 = config1;
this.config2 = config2;
}
public void serviceMethod() {
//using config1 and config2 values
}
}
public concreteServiceA extends AbstractService {
public concreteServiceA(@Value("${config1}") String config1,
@Value("${config2}") String config2) {
super(config1, config2);
}
public void serviceA() {
//using serviceMethod in the abstract class
}
}
public concreteServiceB extends AbstractService {
public concreteServiceB(@Value("${configB1}") String config1,
@Value("${configB2}") String config2) {
super(config1, config2);
}
public void serviceB() {
//using serviceMethod in the abstract class
}
}
答案 0 :(得分:1)
您可以像这样使用 setter 注入或(可能更优雅的)构造函数注入:
public abstract class AbstractService {
protected AbstractService(String config1, String config2) {
this.config1 = config1;
this.config2 = config2;
}
private String config1;
private String config2;
public void serviceMethod() {
//using config1 and config 2 values
}
}
public class ConcreteServiceA extends AbstractService {
public ConcreteServiceA(@Value("${config1a}") String config1, @Value("${config2a}") String config2) {
super(config1, config2);
}
public void serviceA() {
// using serviceMethod in the abstract class
}
}
public class ConcreteServiceB extends AbstractService {
public ConcreteServiceB(@Value("${config1b}") String config1, @Value("${config2b}") String config2) {
super(config1, config2);
}
public void serviceB() {
// using serviceMethod in the abstract class
}
}
但是如果你有很多值,你也可以使用 setter 注入并覆盖每个子类中的 setter。或者您仍然可以使用构造函数注入,但传递一个包含如下配置的容器类:
public class ServiceConfig {
private String config1;
private String config2;
// getters, setters and more properties
}
然后这样传
public abstract class AbstractService {
private ServiceConfig config;
protected AbstractService(ServiceConfig config) {
this.config = config;
}
}
public class ConcreteServiceA extends AbstractService {
public ConcreteServiceA(@Value("${configA}") ServiceConfig config) {
super(config);
}
}
答案 1 :(得分:0)
你可以像下面这样:
public abstract class AbstractService {
public void serviceMethod() {
String config1 = getConfig1();
String config2 = getConfig2();
//using config1 and config 2 values
}
public abstract String getConfig1();
public abstract String getConfig2();
}
public class concreteServiceA extends AbstractService {
@Value("${config1}") private String config1;
@Value("${config2}") private String config2;
public String getConfig1(){
return config1;
}
public String getConfig2(){
return config2;
}
public void serviceA() { // using serviceMethod in the abstract class }
}
public class concreteServiceB extends AbstractService {
@Value("${config1.1}") private String config1;
@Value("${config2.1}") private String config2;
public String getConfig1(){
return config1;
}
public String getConfig2(){
return config2;
}
public void serviceB() { // using serviceMethod in the abstract class }
}
答案 2 :(得分:0)
您可以将您的属性外部化为特定的 bean,这些 bean 将自动装配到具体的类。
Spring 注释 @ConfigurationProperties
允许您根据属性前缀初始化简单的 POJO 属性。
首先创建您的 POJO,我们将注入具体服务:
public class ServiceProperties {
private String config1;
private String config2;
//getters and setters
}
然后在spring扫描的包中创建一个配置类:
@Configuration
public class ServicePropertiesConfiguration {
@Bean
@ConfigurationProperties(prefix = "service-a")
public ServiceProperties serviceAProperties() {
return new ServiceProperties();
}
@Bean
@ConfigurationProperties(prefix = "service-b")
public ServiceProperties serviceBProperties() {
return new ServiceProperties();
}
}
如您所见,prefix
告诉 spring 他必须在哪里搜索属性。您的 application.properties 将如下所示:
service-a.config1=serviceAConfig1
service-a.config2=serviceAConfig2
service-b.config1=serviceBConfig1
service-b.config2=serviceBConfig2
在这个阶段,你会有两个 ServiceProperties
类型的 bean,里面有特定的值
抽象服务如下所示:
public abstract class AbstractService {
private final ServiceProperties serviceProperties;
protected AbstractService(ServiceProperties serviceProperties) {
this.serviceProperties = serviceProperties;
}
public void serviceMethod() {
//using config1 and config 2 values
// serviceProperties.getConfig1();
// serviceProperties.getConfig2();
}
}
在具体的服务中,你必须使用@Qualifier
注解和创建的bean的名字
@Service
public class ConcreteServiceA extends AbstractService{
public ConcreteServiceA(@Qualifier("serviceAProperties") ServiceProperties serviceProperties) {
super(serviceProperties);
}
}
@Service
public class ConcreteServiceB extends AbstractService{
protected ConcreteServiceB(@Qualifier("serviceBProperties") ServiceProperties serviceProperties) {
super(serviceProperties);
}
}