Мне удалось найти работоспособное решение:
Сначала я создал аннотацию для моих значений конфигурации
@Retention(RUNTIME)
@Target({ FIELD })
@Autowired
public @interface ConfigurationValue {
String name();
String defaultValue();
}
Затем я добавил BeanPostProcessor / FactoryBean для своих значений конфигурации
public class ConfigValueBeanProcessor implements BeanPostProcessor, FactoryBean<ConfigSupplier> {
@Autowired
private EnvironmentConfiguration environmentConfiguration;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean.getClass().isAnnotationPresent(MyConfigurableMarkerAnnotationOnClassLevel.class)) {
List<Field> annotatedFields = FieldUtils.getFieldsListWithAnnotation(bean.getClass(), ConfigurationValue.class);
for (Field field : annotatedFields) {
try {
processAnnotatedField(field, bean);
} catch (IllegalAccessException e) {
// do stuff
}
}
}
return bean;
}
private void processAnnotatedField(Field field, Object bean) throws IllegalAccessException {
boolean accessible = field.isAccessible();
field.setAccessible(true);
Object o = field.get(bean);
if (o instanceof ConfigSupplier) {
ConfigurationValue annotation = field.getAnnotation(ConfigurationValue.class);
ConfigSupplier configSupplier = (ConfigSupplier) o;
ConfigSupplier patchedSupplier = configSupplier.withSettingsKeyAndDefault(
annotation.name(), annotation.defaultValue());
field.set(bean, patchedSupplier);
}
field.setAccessible(accessible);
}
@Override
public ConfigSupplier getObject() throws Exception {
return new ConfigSupplier(environmentConfiguration);
}
@Override
public Class<?> getObjectType() {
return ConfigSupplier.class;
}
}
Что происходит, это:
Spring автоматически связывает мой ConfigSupplier со всеми зависимостями. Постпроцессор позже исправляет этого поставщика в жизненном цикле со значением по умолчанию и с правильным ключом конфигурации.
Чувствую себя немного хакером, и я все еще ищу лучшие альтернативы, но это работает. Вероятно, наилучшим способом было бы переопределить org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
и добавить логику для создания компонента и добавить данные аннотации за один шаг вместо моего двухэтапного подхода.