В большинстве проектов Java/Java EE существует общее требование, касающееся того, как различать конфигурации среды, такие как разработка, тестирование, контроль качества, производство и т.д. по этой причине существует множество фреймворков или библиотек для решения этой проблемы:
- Конфигурация дельтаспайка
- Конфигурация Apache Commons
- Сабо
- Апачи Тамайя
- Конфигурация Dropwizard
- Формат данных Джексона YAML
Даже есть предложение по запросу спецификации Java (JSR):
Как эти библиотеки решают проблему
Большинству из этих библиотек требуется иметь точку (точки) внедрения для конфигураций, а также источник (ы) конфигурации (ов), что-то вроде этого:
dev.свойства
:
host=localhost port=5432 schema=public
prod.свойства
:
host=production.com port=5432 schema=public
ConfigurationResolver.java
:
class ConfigurationResolver implements SomeLibraryInterface { @Override public String resolvePropertyFilename() { // probably do some trick to load a global/base configuration // if is not provided for the library return String.format("%s.properties", System.getProperty("MY_ENV", "dev")); } }
MyType.java
:
class MyType { @Configuration(key = "host") String host; @Configuration(key = "port") int port; @Configuration(key = "schema", defaultValue = "public") String schema; }
Обратите внимание, что вся детализация необходима только из-за отсутствия поддержки пользовательских типов
Кроме того, благодаря новым возможностям Java 8, в частности с помощью методов default и некоторых служебных классов, легко добиться такого поведения.
С помощью методов Java 8 по умолчанию
Конфигурация по умолчанию.java
:
interface DefaultConfiguration { default DataSource datasource { // create the DS with host, port and schema return new MyDataSource("localhost", 5432, "public"); } }
Конфигурация устройства.java
:
class DevConfiguration implements DefaultConfiguration { // No need to override methods if they are the same }
Конфигурация Prod
:
class ProdConfiguration implements DefaultConfiguration { default DataSource datasource { return new MyDataSource("production.com", 5432, "public"); } }
ConfigurationFactory.java
:
abstract class ConfigurationFactory { private static final Mapconfigurations = new HashMap<>(); static { configurations.put("development", new DevConfiguration()); configurations.put("production", new ProdConfiguration()); } public static DefaultConfiguration configuration() { return configurations.getOrDefault(System.getProperty("MY_ENV"), new DevConfiguration()); } }
Обратите внимание, что вы можете использовать перечисление вместо карты в качестве фабрики конфигурации.
Плюсы
- Безопасные для типов конфигурации
- Поддержка всех видов типов, а не только
String
,Дата
или примитивы. вы можете указать или примерИсточник данных
,Временные единицы
,JedisPool
и т.д. - Нет преобразования/сопоставления строк с типами
- Больше нет
.свойства
,.xml
или.yml
файлы - Возможность использовать другие источники для заполнения свойств, таких как файлы свойств, база данных, rest API и т.д.
- В вашем приложении не требуется библиотека/фреймворк/зависимость
Аферы
- Изменения в конфигурации требуют компиляции/развертывания (это не должно быть проблемой в 99% случаев)
исходный код
Оригинал: “https://dev.to/cchacin/java-8-type-safe-configuration-with-default-methods-587i”