Подтвердить что ты не робот

Spring аннотация @Value, не использующая значения по умолчанию, когда свойство отсутствует

Я пытаюсь использовать аннотацию @Value в параметрах конструктора следующим образом:

@Autowired
public StringEncryptor(
    @Value("${encryptor.password:\"\"}") String password,
    @Value("${encryptor.algorithm:\"PBEWithMD5AndTripleDES\"}") String algorithm,
    @Value("${encryptor.poolSize:10}") Integer poolSize, 
    @Value("${encryptor.salt:\"\"}") String salt) {
...
}

Когда файл свойств присутствует в пути к классам, свойства загружаются отлично, и тест выполняется отлично. Однако, когда я удаляю файл свойств из пути к классам, я бы ожидал, что будут использоваться значения по умолчанию, например, poolSize будет установлен в 10 или алгоритм для PBEWithMD5AndTripleDES, но это не так.

Запуск кода через отладчик (который работал бы только после изменения @Value("${encryptor.poolSize:10}") Integer poolSize до @Value("${encryptor.poolSize:10}") String poolSize, поскольку он вызывал NumberFormatExceptions). Я обнаружил, что значения по умолчанию не заданы, а параметры находятся в форме:

poolSize = ${encryptor.poolSize:10} или

algorithm = ${encryptor.algorithm:"PBEWithMD5AndTripleDES"}

а не ожидаемый

poolSize = 10 или

algorithm = "PBEWithMD5AndTripleDES"

На основе SPR-4785 должна работать надпись, такая как ${my.property:myDefaultValue}. Но это не для меня!

Спасибо

4b9b3361

Ответ 1

Возможно, инициализация конфигуратора заполнителя свойств завершилась неудачно из-за пропущенного файла свойств, так что заполнители не будут разрешены. Вы можете сконфигурировать его, чтобы игнорировать пропущенные файлы следующим образом (если вы используете пространство имен context для его настройки):

<context:property-placeholder ignore-resource-not-found="true" ... />

Также вам не нужно "..." по умолчанию.

Ответ 2

ignore-resource-not-found = "true" не требуется для выбора значений по умолчанию. Точка указания значения по умолчанию предназначена для его использования, если свойство не найдено нигде.

Я думаю, что последнее предложение в предыдущем ответе указывает на проблему - неправильный EL, который вы должны были первоначально предоставить, но затем удалить из примера. Тот факт, что вы получали исключения для преобразования формата, указывает на это. Обычно Spring автоматически преобразует строки в соответствующий "стандартный" Java-тип, и если вы предоставите собственную реализацию службы преобразования Spring для своих пользовательских объектов - пока ваша служба преобразования определена в контекст приложения.

"ignore-resource-not-found" полезен, когда вы вводите свойства через XML без параметров по умолчанию и не хотите, чтобы контейнер генерировал исключение, создающее экземпляр bean, если свойство не найдено. В таких случаях свойства bean будут инициализированы стандартными значениями Java, например. nulls для объектов, 0s для примитивных числовых значений и т.д.

Ответ 3

В моем случае разрешение значений свойств (и значений по умолчанию) не работало в тесте, где я использую конфигурацию на основе аннотации. Оказалось, что мне пришлось добавить PropertySourcesPlaceholderConfigurer, чтобы свойства действительно разрешались. Это объяснялось в PropertySource Annotation JavaDoc:

Чтобы разрешить ${...} заполнители в определениях или аннотации @Value с использованием свойств из PropertySource, необходимо зарегистрировать PropertySourcesPlaceholderConfigurer. Это происходит автоматически при использовании в XML, но должно быть явно зарегистрировано с использованием статического метода @ Bean при использовании классов @Configuration. См. Раздел "Работа с внешними значениями" в разделе @Configuration Javadoc и "примечание о методах BeanFactoryPostProcessor-return @Bean" @Bean Javadoc для получения более подробной информации и примеров.

Следующий трюк:

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

И если вы хотите добавить отдельные свойства:

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {

    PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();

    Properties properties = new Properties();
    properties.put("batchSize", "250");
    propertySourcesPlaceholderConfigurer.setProperties(properties);

    return propertySourcesPlaceholderConfigurer;
}