首页 > 解决方案 > 使用 ConfigurationProperties 自动装配抽象配置

问题描述

我对 Spring Boot 配置和注入有疑问。我有以下课程:

@Configuration
@ConfigurationProperties("app")
public class AppConfig() {
    public void A() { ...};
}

一切正常。现在我必须根据操作系统拆分这个类,我的想法就是这样,这样做:

public interface AppConfig() {

    void A();
}

public WindowsAppConfig implements AppConfig() {

    public void A()  { //Windows implementation};
}

public LinuxAppConfig implements AppConfig() {
    public void A() { //Linux implementation };
}

@Configuration
public class AppConfigFactory() {
    
    @Bean
    public AppConfig getAppConfig() {
    if(...) { 
        return new WindowsAppConfig;
    } else {
        return new LinuxAppConfig;
    }
}

public class AppStart() {

    @Autowired
    private AppConfig appConfig;
}

现在我得到一个像这样的 IllegalStateException :

java.lang.IllegalStateException: No ConfigurationProperties annotation found on  'appconfig.AppConfig'.

如何以及在何处正确添加 ConfigurationProperties?

标签: javaspringspring-boot

解决方案


我认为使用@Conditional 来更改操作系统的实现可能会更好,就像这篇文章一样。用于评估 OS 的 Spring 表达式

但是我根据您的初始帖子编写示例。

@Component
public class TestConfig {

    private final AppConfig appConfig;

    public TestConfig(AppConfig appConfig){
        this.appConfig = appConfig;
    }

    @PostConstruct
    public void init(){
        appConfig.A();
    }
}

interface AppConfig {

    void A();

    void setFoo(String foo);

    String getFoo();
}

class WindowsAppConfig implements AppConfig {

    private String foo;

    public void A() {
        System.out.println("Windows config");
    }

    @Override
    public void setFoo(String foo) {
        this.foo = foo;
    }

    @Override
    public String getFoo() {
        return foo;
    }
}

class LinuxAppConfig implements AppConfig {

    private String foo;

    public void A() {
        System.out.println("Linux config");
    }

    @Override
    public void setFoo(String foo) {
        this.foo = foo;
    }

    @Override
    public String getFoo() {
        return foo;
    }
}

@Configuration
@ConfigurationProperties("factory")
class AppConfigFactory {

    private boolean useWin ;

    @Bean
    @ConfigurationProperties("app")
    public AppConfig getAppConfig() {
        if (useWin) {
            return new WindowsAppConfig();
        } else {
            return new LinuxAppConfig();
        }
    }

    public boolean isUseWin() {
        return useWin;
    }

    public void setUseWin(boolean useWin) {
        this.useWin = useWin;
    }
}

以下是 application.yml 示例

app:
  foo: Foo

factory:
  use-win: true

推荐阅读