Как избежать дублирования конвертера в Spring ConversionService?

У меня есть собственный StringToBooleanConverter, который должен заменить конвертер по умолчанию, поставляемый с Spring. Таким образом, исходный и целевой типы абсолютно одинаковы. Но вместо замены существующего конвертера Spring добавлен мой конвертер. Если я отлаживаю приложение, я вижу оба преобразователя в одной записи карты преобразователей Map ConversionService #.

ConversionService настроен следующим образом:

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

@Bean
open fun stringToBooleanConverter() = MyStringToBooleanConverter()

// some more converters not relevant here ...

Проблема в том, что иногда используются неправильные преобразователи.

Как я могу удалить / заменить / скрыть / деактивировать конвертер, поставляемый Spring?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
813
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Обновлять

Если вы используете 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)

Вы можете удалить bean-компонент с помощью:

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

Оригинальное предложение

Это связано со связанным вопросом здесь: https://stackoverflow.com/a/12447211/857994. На самом деле вы просто хотите удалить существующий компонент.

Вы можете получить ссылку на фабрику bean-компонентов и вручную удалить с нее старый bean-компонент. Я думаю, что наиболее прямым методом, вероятно, будет тот, который предлагается в комментарии: "Just implement BeanFactoryAware and then cast BeanFactory with DefaultListableBeanFactory".

Я не верю, что есть способ вообще прекратить подачу бобов, поскольку они происходят из самой весны. Вы можете аннотировать свои собственные bean-компоненты, чтобы избежать автосоединения, хотя я не знаю, как вы могли бы добиться этого на bean-компонентах, предоставляемых Spring.

Большое спасибо за ваши усилия. Но собственный StringToBooleanConverter Spring не указан в контексте (с ctx..getBeanDefinitionNames()), я могу видеть только свой собственный конвертер. Это невозможно даже для компонента по типу с context.getBean(StringToBooleanConverter::class), потому что StringToBooleanConverter не является общедоступным. Это похоже на очень неэлегантный уголок Spring Framework.

deamon 19.09.2018 08:26

Собственные конвертеры Spring не зарегистрированы как beans, как вы можете видеть в DefaultConversionService. Таким образом, невозможно удалить преобразователь, удалив bean-компонент.

deamon 19.09.2018 10:06
Ответ принят как подходящий

Хитрость заключается в том, чтобы определить собственный ConversionServiceFactoryBean, переопределить метод createConversionService и удалить StringToBooleanConverter, зарегистрированный самим Spring:

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.

Другие вопросы по теме