首页 > 解决方案 > 抽象类中的抽象属性

问题描述

我有一个抽象类,其中包含一些使用@Value 设置的配置属性值。我想重用抽象类,但要使用另一组配置属性。问题是,这些属性值已经在抽象类中设置,并且所有具体类都继承了它。

我曾想过:

  1. 在抽象类中创建另一组配置值,但这似乎是在创建重复项,但是当将来还有第三组配置值时,这不太可扩展。

  2. 将抽象类中配置值的可访问性从私有更改为受保护,并让具体类覆盖它。但我不确定这种覆盖是否良好,因为它似乎会混淆实际配置值是什么。

  3. 创建另一个类似于“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
      }
    }

标签: javaspring

解决方案


您可以使用 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);
    }
}

推荐阅读