Конфигурация
Модуль конфигурации отвечает за отображение значений из файлов конфигурации на классы в Kora и их последующее использование для настройки приложения.
HOCON¶
Поддержка HOCON реализована с помощью Typesafe Config. HOCON — это формат конфиг-файлов, основанный на JSON. Формат менее строгий нежели JSON и обладает слегка другим синтаксисом.
services {
foo {
bar = "SomeValue"
baz = 10
propRequired = ${REQUIRED_ENV_VALUE}
propOptional = ${?OPTIONAL_ENV_VALUE}
propDefault = 10
propDefault = ${?NON_DEFAULT_ENV_VALUE}
propReference = ${services.foo.bar}Other${services.foo.baz}
propArray = ["v1", "v2"]
propArrayAsString = "v1, v2"
propMap = {
"k1" = "v1"
"k2" = "v2"
}
propObject = {
p1 = "v1"
p2 = "v2"
}
propObjects = [
{
p1 = "v1"
p2 = "v2"
},
{
p1 = "v3"
p2 = "v4"
}
]
}
}
Отображение конфигурации в коде:
@ConfigSource("services.foo")
public interface FooConfig {
String bar();
Integer baz();
String propRequired();
@Nullable
String propOptional();
Integer propDefault();
String propReference();
List<String> propArray();
List<String> propArrayAsString();
Map<String, String> propMap();
@ConfigValueExtractor
public interface ObjectConfig {
String p1();
String p2();
}
ObjectConfig propObject();
List<ObjectConfig> propObjects();
}
@ConfigSource("services.foo")
interface FooConfig {
fun bar(): String
fun baz(): Int
fun propRequired(): String
fun propOptional(): String?
fun propDefault(): Int
fun propReference(): String
fun propArray(): List<String>
fun propArrayAsString(): List<String>
fun propMap(): Map<String, String>
@ConfigValueExtractor
interface ObjectConfig {
fun p1(): String
fun p2(): String
}
fun propObject(): ObjectConfig
fun propObjects(): List<ObjectConfig>
}
Подключение¶
Зависимость build.gradle
:
Модуль:
Зависимость build.gradle.kts
:
Модуль:
Файл¶
По умолчанию ожидаются файлы конфигурации reference.conf и application.conf
Во-первых, все файлы reference.conf
объединяются, во-вторых, файл application.conf
накладывается на неразрешенный
файл reference.conf
, результат вычисляется и проверяется что все значения переменных доступны.
Предполагается что конфигурация приложения находится в файле application.conf
, а конфигурации библиотек в reference.conf
.
Приоритет считывания application.conf
файла конфигурации:
- Использовать файл из
config.resource
если указан (файл изresources
директории) - Использовать файл из
config.file
если указан (файл из файловой системы) - Использовать файл
application.conf
если имеется (файл изresources
директории) - Используется пустой файл конфигурации если все указанное выше отсутствует
YAML¶
Поддержка YAML реализована с помощью SnakeYAML.
services:
foo:
bar: "SomeValue"
baz: 10
propRequired: ${REQUIRED_ENV_VALUE}
propOptional: ${?OPTIONAL_ENV_VALUE}
propDefault: ${?NON_DEFAULT_ENV_VALUE:10}
propReference: ${services.foo.bar}Other${services.foo.baz}
propArray: ["v1", "v2"]
propArrayAsString: "v1, v2"
propMap:
k1: "v1"
k2: "v2"
propObject:
p1: "v1"
p2: "v2"
propObjects:
- p1: "v1"
p2: "v2"
- p1: "v1"
p2: "v2"
Отображение конфигурации в коде:
@ConfigSource("services.foo")
public interface FooConfig {
String bar();
Integer baz();
String propRequired();
@Nullable
String propOptional();
Integer propDefault();
String propReference();
List<String> propArray();
List<String> propArrayAsString();
Map<String, String> propMap();
@ConfigValueExtractor
public interface ObjectConfig {
String p1();
String p2();
}
ObjectConfig propObject();
List<ObjectConfig> propObjects();
}
@ConfigSource("services.foo")
interface FooConfig {
fun bar(): String
fun baz(): Int
fun propRequired(): String
fun propOptional(): String?
fun propDefault(): Int
fun propReference(): String
fun propArray(): List<String>
fun propArrayAsString(): List<String>
fun propMap(): Map<String, String>
@ConfigValueExtractor
interface ObjectConfig {
fun p1(): String
fun p2(): String
}
fun propObject(): ObjectConfig
fun propObjects(): List<ObjectConfig>
}
Подключение¶
Зависимость build.gradle
:
Модуль:
Зависимость build.gradle.kts
:
Модуль:
Файл¶
По умолчанию ожидаются файлы конфигурации reference.yaml
и application.yaml
.
Во-первых, все файлы reference.yaml
объединяются, во-вторых, файл application.yaml
накладывается на неразрешенный
файл reference.yaml
, результат вычисляется и проверяется что все значения переменных доступны.
Предполагается что конфигурация приложения находится в файле application.yaml
, а конфигурации библиотек в reference.yaml
.
Приоритет считывания application.yaml
файла конфигурации:
- Использовать файл из
config.resource
если указан (файл изresources
директории) - Использовать файл из
config.file
если указан (файл из файловой системы) - Использовать файл
application.yaml
если имеется (файл изresources
директории) - Используется пустой файл конфигурации если все указанное выше отсутствует
Пользовательские конфигурации¶
Пользовательская конфигурация предоставляет собой отображение файла конфигурации на пользовательский интерфейс. Такой пользовательский интерфейс в последствии может быть внедрен как зависимость наравне с другими компонентами.
В приложении¶
Для создания пользовательских конфигураций следует использовать аннотацию @ConfigSource
:
Этот пример кода добавит в контейнер экземпляр класса FooServiceConfig
, который при создании будет ожидать конфигурацию следующего вида:
После этого класс FooServiceConfig
уже можно использовать как зависимость в других классах:
В библиотеке¶
Для создания пользовательских конфигураций в рамках пользовательских библиотеках следует использовать аннотацию @ConfigValueExtractor
которая создаст правила обработки файла конфигурации в экземпляр класса конфигурации.
Рассмотрим пример когда есть такой класс конфигурации:
Для того чтобы библиотека предоставляла конфигурацию, требуется реализовать фабрику в модуле:
Фабрика будет ожидать конфигурацию следующего вида:
Затем подключив модуль FooLibraryModule
в приложении, конфиг FooServiceConfig
можно использовать как зависимость в других классах.
Обязательные значения¶
По умолчанию все значения объявленные в конфиге считаются обязательными (NotNull) и должны присутствовать в файле конфигурации.
Необязательные значения¶
Если есть необходимость указать значение из файла конфигурации как необязательное, то можно воспользоваться таким форматом:
Предлагается использовать аннотацию @Nullable
над сигнатурой метода:
@ConfigSource("services.foo")
public interface FooServiceConfig {
@Nullable
String bar();
int baz();
}
Предполагается использовать Kotlin Nullability синтаксис и помечать такой параметр как Nullable:
Значения по умолчанию¶
Если есть необходимость использовать задать в отображении значение по умолчанию, то можно воспользоваться default
модификатором:
Внедрение конфигурации¶
Можно внедрять базовый класс ru.tinkoff.kora.config.common.Config
который предоставляет из себя общую абстракцию над
отображением файла конфигурации. Результирующие отображение конфигурации состоит из нескольких слоев которые представляют из себя:
- Переменные окружения
- Системные переменные
- Файл конфигурации
Переменные окружения¶
В случае если требуется внедрить конфигурацию только переменных окружения,
то для этого можно использовать аннотацию @Environment
как тег для класса конфигурации:
Системные переменные¶
В случае если требуется внедрить конфигурацию только системных переменных,
то для этого можно использовать аннотацию @SystemProperties
как тег для класса конфигурации:
Файл конфигурации¶
В случае если требуется внедрить полную конфигурацию приложения которая состоит только из файла конфигурации,
то для этого можно использовать аннотацию @ApplicationConfig
как тег для класса конфигурации:
Результирующая конфигурация¶
В случае если требуется внедрить полную конфигурацию приложения которая состоит из файла конфигурации, переменных окружения и системных переменных, то для этого требуется просто внедрить класс конфигурации без тега:
Рекомендации¶
Совет
Мы не рекомендуем использовать напрямую ru.tinkoff.kora.config.common.Config
как зависимость в компонентах,
так как при обновлении конфигурации это повлечет обновление всех компонент графа которые используют его у себя,
рекомендуется всегда создавать пользовательские конфигурации.
Наблюдатель¶
По умолчанию в Kora работает наблюдатель за файлом конфигурации который обновляет его содержимое, что влечет в случае изменения файла конфигурации обновление графа зависимостей для компонент которые затронули изменения.
Можно отключить наблюдатель с помощь:
- Переменной окружения
KORA_CONFIG_WATCHER_ENABLED
- Системного свойства
kora.config.watcher.enabled
Поддерживаемые типы¶
Экстракторы конфигурации предоставляют обширный список поддерживаемых типов, который охватывает большинство из того,
что вам может понадобиться для указания в пользовательских конфигурациях, либо вы можете расширить поведение собственным ConfigValueExtractor<T>
компонентом.
Список поддерживаемых типов
- boolean / Boolean
- short / Short
- int / Integer
- long / Long
- double / Double
- float / Float
- double[]
- String
- BigInteger
- BigDecimal
- Period
- Duration
- Size
- Properties
- Pattern
- UUID
- Properties
- LocalDate
- LocalTime
- LocalDateTime
- OffsetTime
- OffsetDateTime
- Enum (любой пользовательский ENUM тип)
List<T>
(гдеT
любой из выше перечисленных типов)Set<T>
(гдеT
любой из выше перечисленных типов)Map<String, T>
(гдеT
любой из выше перечисленных типов)Either<A, B>
(гдеA
иB
любой из выше перечисленных типов)
Размер¶
Size
- специальный тип который позволяет задавать размер байт в удобной человеку системе исчислений по стандарту IEEE 1541—2002 (двоичный), так и в стандарте СИ (десятичный).
Примеры значений:
1Mb
- 1 мегабайт (1.000.000
байт)1Mib
- 1 мегабит (1.048.576
байт)1024b
- 1024 байт1024
- 1024 байт
Если указано просто число без суффикса, то считается что указаны байты.