如何避免Spring ConversionService中的Converter重复?

时间:2018-09-18 14:55:24

标签: java spring type-conversion

我有一个自定义StringToBooleanConverter,应该替换Spring附带的默认转换器。因此,源类型和目标类型完全相同。但是添加了我的转换器,而不是替换现有的Spring转换器。如果我调试应用程序,则可以在Map ConversionService#converters的同一映射条目中看到两个转换器。

ConversionService的配置如下:

@Bean
open fun conversionService(converters: Set<Converter<*, *>>) =
        ConversionServiceFactoryBean().apply { setConverters(converters) }

@Bean
open fun stringToBooleanConverter() = MyStringToBooleanConverter()

// some more converters not relevant here ...

问题在于有时会使用错误的转换器。

如何删除/替换/隐藏/停用Spring提供的转换器?

2 个答案:

答案 0 :(得分:1)

诀窍是定义一个自定义ConversionServiceFactoryBean,以覆盖方法createConversionService,并删除Spring本身注册的StringToBooleanConverter

class ConversionServiceFactoryWithoutStringToBooleanConverter : ConversionServiceFactoryBean() {

    override fun createConversionService(): GenericConversionService {
        val conversionService = super.createConversionService()
        conversionService.removeConvertible(String::class.java, java.lang.Boolean::class.java)
        return conversionService
    }
}

但是,在这种情况下,不必删除Spring转换器,因为对于特定的源类型和目标类型,如果有多个转换器,Spring将按顺序尝试它们,并且用户注册的转换器将排在最前面。促使我进行此调查的行为实际上与另一个与ConversionService不相关的错误有关。

答案 1 :(得分:0)

更新

如果您正在运行Spring Boot,则可以像这样启动应用程序并按以下方式获取bean。

ApplicationContext ctx = SpringApplication.run(Main.class, args);
DispatcherServlet servlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");

您可以使用以下命令列出所有bean:

ctx.getBeanDefinitionNames()

请注意,大多数只是以带有小写首字母的类名称命名(为您假设“ stringToBooleanConverter”)。有些在前面有软件包名称,然后是。您可以在调试器中轻松查看:)。

您可以找到像这样的特定类类型的Bean(请注意,在我的情况下,此定义返回null;因此在我的应用程序中似乎没有这种依赖关系):

ctx.getBean(StringToBooleanConverter.class)

您可以使用以下方法删除bean:

((AnnotationConfigEmbeddedWebApplicationContext)
     ctx).removeBeanDefinition("yourBeanName")

原始建议

这与此处的一个相关问题有关:https://stackoverflow.com/a/12447211/857994。实际上,您只想删除现有的bean。

您可以获得对bean工厂的引用,并手动从中删除旧的bean。我认为最直接的方法可能是评论中建议的方法:"Just implement BeanFactoryAware and then cast BeanFactory with DefaultListableBeanFactory"

我不认为有一种方法可以首先停止提供bean,因为它来自spring本身。您可以注释自己的bean以避免自动装配,但是我不知道如何在春季提供的bean上实现该目的。