【问题标题】:How to avoid duplicate Converter in Spring ConversionService?如何避免 Spring ConversionService 中的重复 Converter?
【发布时间】:2019-02-22 15:44:11
【问题描述】:

我有一个自定义的 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 提供的转换器?

【问题讨论】:

    标签: java spring type-conversion


    【解决方案1】:

    更新

    如果你正在运行 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 以避免自动装配,但我不知道您如何在 spring 提供的 bean 上实现这一点。

    【讨论】:

    • 非常感谢您的努力。但是Spring自带的StringToBooleanConverter没有在上下文中列出(有ctx..getBeanDefinitionNames()),只能看到我自己的转换器。甚至不可能按类型使用context.getBean(StringToBooleanConverter::class) 来处理bean,因为StringToBooleanConverter 不是公开的。它看起来像是 Spring 框架的一个非常不雅的角落。
    • Spring 自己的转换器没有注册为 bean,正如您在 DefaultConversionService 中看到的那样。所以不可能通过移除一个bean来移除一个转换器。
    【解决方案2】:

    诀窍是定义一个自定义的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 无关的错误有关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 2016-11-17
      • 2021-08-17
      相关资源
      最近更新 更多