Можно ли использовать во вложенном классе свойств конфигурации java Spring значение из родительского элемента для инициализации дочернего элемента?

У меня есть веб-служба SpringBoot 2, Kotlin/Java, которая использует @ConfigurationProperties для загрузки вложенного набора классов / свойств для использования во время выполнения. Все работает правильно, за исключением одного: я не могу понять, как передать значение (код) из родительского класса (TenantProperties) в его вложенный дочерний класс (DatabaseProperties). В следующем фрагменте, извлеченном из другого родителя с соответствующими аннотациями, я пытаюсь передать код в TenantProperties в DatabaseProperties при его создании. Что бы я ни пробовал, родитель всегда передает потомку null. Буду признателен за любые предложения.

class TenantProperties(
    var code: String? = null,
    var id: String? = null,
    var name: String? = null,
    var db: DatabaseProperties = DatabaseProperties(code),
    var blob: BlobProperties = BlobProperties(code)
) {
    class DatabaseProperties(
        var code: String?,
        var uriTemplate: String? = null,
        var username: String? = null,
        var password: String? = null
    ) {
        fun connectionString() = "$uriTemplate".format(username, password, code)
    }
}

1 ответ

Решение

В вашем примере вы инициализируете классы вместе с родительским объектом. Параметры конфигурации пружины вводятся позже. Таким образом, ваши вложенные классы всегда инициализируются значением по умолчанию, поэтому настроенныйcode никогда не будет передан.

Чтобы заставить ваш код работать, я предлагаю сделать классы внутренними классами (чтобы позволить им получить доступ к внешнему) и лениво инициализировать свойство post-built:

@Configuration
@ConfigurationProperties(value =  "my")
class TenantProperties {

    lateinit var code: String
    lateinit var id: String
    lateinit var name: String

    val db = DatabaseProperties()

    inner class DatabaseProperties {
        lateinit var uriTemplate: String
        lateinit var username: String
        lateinit var password: String
        val connectionString by lazy { "$uriTemplate".format(username, password, code) }
    }
}

Делаем все переменные lateinitвы получаете некоторую безопасность типов. Чтобы сделать его еще более надежным, вы можете добавить несколько валидаторов:

@Configuration
@ConfigurationProperties(value =  "my", ignoreUnknownFields = false, ignoreInvalidFields = false)
class TenantProperties {

    @NotNull lateinit var code: String
    @NotNull lateinit var id: String
    @NotNull lateinit var name: String

    val db = DatabaseProperties()

    inner class DatabaseProperties {
        @NotNull lateinit var uriTemplate: String
        @NotNull lateinit var username: String
        @NotNull lateinit var password: String
        val connectionString by lazy { "$uriTemplate".format(username, password, code) }
    }
}

теперь твой application.properties может выглядеть так:

my.code=aCode
my.id=anId
my.name=aName
my.db.uri-template=http://localhost
my.db.username=admin
my.db.password=pw
Другие вопросы по тегам