👨‍💻 Spring Tips: работаем со свойствами



Более миллиона раз разработчики обращались к вопросу на StackOverflow о том, как получить значение из application.properties. Возможно, вы удивитесь (хотя я очень сильно сомневаюсь в этом), но отмеченный как верный ответ с @Value – это не единственный способ. И далеко не всегда самый удобный.



Способ №1: @Value



Аннотация @Value используется для инъекции отдельных значений из файла конфигурации. Например:





@Value("${property.name}")

private String propertyName;




Пожалуй, самый простой, но не самый поддерживаемый вариант, из-за отсутствия группировки и большого количества дублирующего кода, когда значений, с которыми надо работать, становится довольного много.



Способ №2: @ConfigurationProperties



Аннотация @ConfigurationProperties используется для группировки связанных свойств в объект класса. Свойства могут настраиваться через .properties и .yaml файлы, переменные окружения и т.д.



Типичное использование @ConfigurationProperties может выглядеть следующим образом:





@ConfigurationProperties(prefix = "app")

@Component

@Getter

@Setter

public class ApplicationProperties {

private String name;

}



@SpringBootTest(properties = "app.name=my-app")

class ApplicationPropertiesTest {



@Autowired

private ApplicationProperties applicationProperties;



@Test

void appName() {

var appName = applicationProperties.getName();

assertEquals("my-app", appName);

}

}




Да, нужно будет создать отдельный класс, зато преимуществ у этого подхода относительно @Value довольно много. Перечислим некоторые из них:



– Группировка по префиксу

– Возможность иерархического представления свойств

– Это бин и этим всё сказано :)

@ConfigurationPropertiesBinding

– Кто сможет назвать ещё парочку преимуществ в комментариях?)



Отдельно отметим @ConfigurationPropertiesBinding. Допустим, нам нужно добавить новое свойство version, которое будет представлять класс Version для обработки семантического версионирования (major.minor.patch).





@ConfigurationProperties(prefix = "app")

@Component

@Getter

@Setter

public class ApplicationProperties {

private String name;

private Version version;

}





Для преобразования строкового значения из конфигурации в объект класса Version нам потребуется конвертор, который как раз будет отмечен аннотацией @ConfigurationPropertiesBinding:





@ConfigurationPropertiesBinding

@Component

class SemVerPropertyConverter implements Converter<String, Version> {



@Override

public Version convert(String source) {

return StringUtils.hasLength(source) ? Version.parse(source) : null;

}

}





Пример использования:





@SpringBootTest(properties = {

"app.name=my-app",

"app.version=1.1.0"

})

class ApplicationPropertiesTest {



@Autowired

private ApplicationProperties applicationProperties;



@Test

void appVersion() {

Version version = applicationProperties.getVersion();

assertEquals(1, version.getMajorVersion());

assertEquals(1, version.getMinorVersion());

assertEquals(0, version.getPatchVersion());

}

}




Подробнее про @ConfigurationProperties и @ConfigurationPropertiesBinding вы можете прочитать в документации.



Способ №3: Environment



А если вы хотите обойтись без специальных аннотаций, можно использовать Environment:





@Autowired

private Environment env;



public void someMethod() {

String property = env.getProperty("property.name");

}




#SpringBoot #SpringTips