我的用例有点奇怪,但基本上,我想读取一个yaml文件的一部分并将其映射到spring应用程序中的相应java对象。这是春天非常常见且简单的操作(只需使用@ConfigurationProperties)。
但是,在我的情况下,我想在生命周期的早期(即BeanFactoryPostProcessor挂钩时)完成此读取 - 以便使用yml中指定的指令动态创建多个bean。
我可以使用application.properties但不能使用application.yml
我希望使用yml来将yml的一部分映射到POJO,并使用分层映射文件和数据结构(列表,地图等)。
以下是如何阅读application.properties的示例。 https://blog.pchudzik.com/201705/dynamic-beans/
我在https://github.com/balamuru/yaml-loader设置了一个简单的骨架项目,尝试不同的技巧。 有什么想法吗?
@Component
@EnableConfigurationProperties(SampleDataConfig.class)
class ConfigurableBeanFactory implements BeanFactoryPostProcessor, InitializingBean {
private List<String> beanInstances = new ArrayList<>();
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
final BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
Map<String, SampleDataConfig> beans = beanFactory.getBeansOfType(SampleDataConfig.class);
System.err.println("");
beanInstances.forEach(instance -> {
registry.registerBeanDefinition(instance, BeanDefinitionBuilder
.rootBeanDefinition(SampleDataConfig.class)
.addConstructorArgValue(instance)
.getBeanDefinition());
});
}
@Override
public void afterPropertiesSet() throws Exception {
// this.beanInstances = asList(PropertiesLoaderUtils
// .loadProperties(new ClassPathResource("/application.properties"))
// .getProperty("dynamic-beans.instances", "")
// .split(","));
/**
* Rather than reading from application.properties,
* I would like to be able to load up the relevant prefix qualified segments (com.foo.bar.stuff) mapping to my POJO (SampleDataConfig,class)
* loaded from application.yml
*/
}
}
在内部,spring使用以下机制,但我希望有一种更简单的方法可以在不重新发明弹簧的情况下利用它:)
public class ConfigurationPropertiesBindingPostProcessor ...{
.
.
private void postProcessBeforeInitialization(Object bean, String beanName,
ConfigurationProperties annotation) {
Object target = bean;
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(
target);
factory.setPropertySources(this.propertySources);
factory.setValidator(determineValidator(bean));
// If no explicit conversion service is provided we add one so that (at least)
// comma-separated arrays of convertibles can be bound automatically
factory.setConversionService(this.conversionService == null
? getDefaultConversionService() : this.conversionService);
if (annotation != null) {
factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());
factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());
factory.setExceptionIfInvalid(annotation.exceptionIfInvalid());
factory.setIgnoreNestedProperties(annotation.ignoreNestedProperties());
if (StringUtils.hasLength(annotation.prefix())) {
factory.setTargetName(annotation.prefix()); //====> use annotation prefix
}
}
try {
factory.bindPropertiesToTarget(); //===> bind properties
}
由于
答案 0 :(得分:-1)
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("application.yml"));
configProperty = yaml.getObject();
Set<Object> keys = configProperty.keySet();
以下是我的YAML配置,如下所示:
template:
config:
broker-urls:
- tcp://127.0.0.1:61616
- tcp://127.0.0.1:61617
- tcp://127.0.0.1:61618
qeues:
- Test
- Demo
- Qeue3
应用上述代码后,您将获得如下所示的转换属性:
template.config.broker-urls[0]=tcp://127.0.0.1:61616
template.config.broker-urls[1]=tcp://127.0.0.1:61617
template.config.broker-urls[1]=tcp://127.0.0.1:61618
template.config.qeues[0]=Test
template.config.qeues[1]=Demo
template.config.qeues[1]=Qeue3