我有一个公开JSON REST API弹簧启动应用程序。用于将对象映射到JSON它使用内置的杰克逊ObjectMapper配置成通过弹簧引导。
现在,我需要从一个YAML文件中读取一些数据,我发现一个简单的方法来做到这一点是利用杰克逊 - 为了这个,我需要声明一个不同的ObjectMapper转换YAML对象。我宣布这个新的映射豆具有特定名称,以便能够从YAML文件中读取注入它在我的服务交易:
@Bean(YAML_OBJECT_MAPPER_BEAN_ID)
public ObjectMapper yamlObjectMapper() {
return new ObjectMapper(new YAMLFactory());
}
但我需要一种方法来告诉原来的JSON ObjectMapper的其他所有“客户”使用bean来保持。所以基本上我需要在原豆一@Primary注解。有没有办法实现这一目标,而不必重新声明原ObjectMapper在我自己的配置(我不得不通过弹簧引导代码挖找到并复制它的配置)?
一个解决方案,我发现是声明一个FactoryBean为ObjectMapper并使其返回已声明豆,在提出这个答案。我发现通过调试我原来的豆腐被称为“_halObjectMapper”,所以我的FactoryBean将搜索这个bean,并返回它:
public class ObjectMapperFactory implements FactoryBean<ObjectMapper> {
ListableBeanFactory beanFactory;
public ObjectMapper getObject() {
return beanFactory.getBean("_halObjectMapper", ObjectMapper.class);
}
...
}
然后在我的配置I类声明为@Primary豆,以确保它是自动装配的首选:
@Primary
@Bean
public ObjectMapperFactory objectMapperFactory(ListableBeanFactory beanFactory) {
return new ObjectMapperFactory(beanFactory);
}
不过,我不是100%满意这个解决方案,因为它依赖于它是不是我的控制下的bean的名字,也似乎是一个黑客。是否有一个清晰的解决方案?
谢谢!
您可以定义两个ObjectMapper
豆类和一个声明为一级,如:
@Bean("Your_id")
public ObjectMapper yamlObjectMapper() {
return new ObjectMapper(new YAMLFactory());
}
@Bean
@Primary
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
一旦这样做,你可以用你的objectmapper豆@Qualifier
注释,例如:
@Autowired
@Qualifier("Your_id")
private ObjectMapper yamlMapper;
更新
您可以动态地添加ObjectMapper
到Spring的bean工厂在运行时,如:
@Configuration
public class ObjectMapperConfig {
@Autowired
private ConfigurableApplicationContext context;
@PostConstruct
private void init(){
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ObjectMapper.class);
builder.addConstructorArgValue(new JsonFactory());
DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getBeanFactory();
factory.registerBeanDefinition("yamlMapper", builder.getBeanDefinition());
Map<String, ObjectMapper> beans = context.getBeansOfType(ObjectMapper.class);
beans.entrySet().forEach(System.out::println);
}
}
上面的代码添加一个新的豆到context
在不改变现有的bean(sysout
打印中的端部两个bean init
方法)。然后,您可以使用“yamlMapper”作为限定词的任何地方自动装配它。
更新2(从提问作者):
在“更新”工作建议,并在此解决方案的简化版本:
@Autowired
private DefaultListableBeanFactory beanFactory;
@PostConstruct
private void init(){
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(YAMLMapper.class);
beanFactory.registerBeanDefinition("yamlMapper", builder.getBeanDefinition());
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句