如何避免弹簧转换服务中的重复转换器?



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

转换服务配置如下:

@Bean
open fun conversionService(converters: Set<Converter<*, *>>) =
ConversionServiceFactoryBean().apply { setConverters(converters) }
@Bean
open fun stringToBooleanConverter() = MyStringToBooleanConverter()
// some more converters not relevant here ...

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

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

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

更新

如果你运行的是 Spring Boot,你可以像这样启动你的应用程序,并得到一个 bean,如下所示。

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

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

ctx.getBeanDefinitionNames()

请注意,大多数只是以小写首字母命名为类名(为您假设"stringToBooleanConverter"(。 有些前面有包名称,然后是那个。 您可以在调试器中轻松:)检查这一点。

你可以像这样找到一个特定类类型的 bean(请注意,在我的情况下,这个定义返回 null;所以这个依赖项似乎不在我的应用程序中(:

ctx.getBean(StringToBooleanConverter.class)

您可以使用以下方法删除豆子:

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

原始建议

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

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

我不相信有办法首先阻止豆子的供应,因为它来自春天本身。 您可以注释自己的豆子以避免自动布线,我不知道如何在弹簧提供的豆子上实现这一点。

最新更新