一个 class 的 bean 的多个实例填充了来自 application.properties 的值

Multiple instances of a bean of one class filled with values from application.properties

我打算使用 spring-boot-actuator 为 Spring 启动应用程序编写一些 HealtCheckContributors。因此,我实施了其中两个。当然,它们用于检查不同应用程序的运行状况,但结构几乎相同,除了配置属性,...

SonarQube 对此表示不满,我想知道是否可以进行一次健康检查 class,但实例化次数与 application.properties 中定义的一样多。 一个例子:

application.properties:

# actuator
app1.management.baseUrl=http://localhost:10000
app1.management.name=app1HealthCheckContributor
app2.management.basUrl=http://localhost:10001
app2.management.name=app2HealthCheckContributor

HealthCheckContributor 对于 app1:

@Slf4j
@Component("xxx")
public class App1HealthCheckContributor extends AbstractHealthIndicator {

    private final App1Properties app1Properties;

    public App1HealthCheckContributor(final App1Properties app1Properties) {
        this.app1Properties = app1Properties;
    }

    @Override
    protected void doHealthCheck(Health.Builder builder) {...}
}

...每个 HealthCheckContributor 的代码仅在其 appXProperties.

中不同

有没有可能有某种基础 class 像:

@Slf4j
@Component()
public class MyHealthCheckContributor extends AbstractHealthIndicator {

    private final MyProperties myProperties;

    public MyHealthCheckContributor(final MyProperties myProperties) {
        this.myProperties = myProperties;
    }

    @Override
    protected void doHealthCheck(Health.Builder builder) {...}
}

并让 Spring Boot 负责实例化两个 HealthCheckContributors(在我们的例子中是 App1HealthCheckContributorApp2HealthCheckContributor)? 这将消除代码重复。

属性示例 class 文件:

@Slf4j
@Data
@ConfigurationProperties(prefix = "app1.management")
public class App1Properties {
    private String baseUrl;
    private String ...;
}

我怎样才能做到这一点,application.properties 文件看起来如何才能实现我想要做的事情?

最后一题:

假设 doHealthCheck 中的代码对于要检查的所有应用程序完全相同,您可以执行以下操作。

您将从创建单个运行状况检查开始 class:

@Slf4j
public class AppHealthCheckContributor extends AbstractHealthIndicator {

    private final AppProperties appProperties;

    public App1HealthCheckContributor(final AppProperties appProperties) {
        this.appProperties = appProperties;
    }

    @Override
    protected void doHealthCheck(Health.Builder builder) {...}
}

属性模型如下:

@Slf4j
@Data
public class AppProperties {
    private String baseUrl;
    private String name;
}

这意味着配置将类似于以下内容(在 application.yml 中):

health-check:
  apps:
    - baseUrl: http://localhost:10000
      name: app1
    - baseUrl: http://localhost:10001
      name: app2

最后,您需要为每个应用程序创建一个 bean 并在应用程序上下文中注册它们:

@Slf4j
@Data
@Configuration
@ConfigurationProperties(prefix = "health-check")
public class AllAppPropertiesConfiguration {
    private List<AppProperties> apps;

    @Autowired
    private GenericApplicationContext applicationContext;

    @PostConstruct
    fun init() {
        for (AppProperties app : apps) {
            applicationContext.registerBean(app.getName(), AppHealthCheckContributor.class, app);
        }
    }
}