Spring Конвертеры ConversionService, добавляющие конвертеры
Я искал следующую проблему, но не смог найти ответ.
Я хочу использовать услугу преобразования spring, написав свой собственный конвертер, который реализует org.springframework.core.convert.converter.Converter.
Затем я добавляю свой пользовательский конвертер, как показано ниже:
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean id="StringToLoggerConverter" class="com.citi.spring.converter.LoggerConverter" />
</list>
</property>
</bean>
При выполнении вышеописанной инициализации моего приложения завершается сбой, потому что я переопределяю bean conversionService и регистрирую только мой пользовательский конвертер.
Как я могу не переопределять функцию conversionService и добавлять только свой собственный конвертер в список конвертеров, сохраняя при этом существующие?
Спасибо заранее.
Ответы
Ответ 1
При экспериментировании разными способами и даже после spring исходного кода в некоторых случаях я сталкивался с интересной вещью.
Единственный способ, с помощью которого я использовал функцию conversionService без переопределения существующих конвертеров с моими собственными, заключался либо в расширении, либо в повторной реализации функции conversionService, вызывающей метод super class afterPropertiesSet() для регистрации преобразователей по умолчанию, а затем для добавления пользовательских.
Но даже если бы я использовал этот способ, во время выполнения я получал исключение, которое не было найдено для моих конкретных типов (например, от String to Logger).
Это вызвало мой интерес, и я последовал за spring исходным кодом, чтобы узнать, почему и я понял, что spring пытался найти собственный конвертер, зарегистрированный в PropertyEditor. Я не знаю, почему это происходит. Я должен добавить здесь, что мое приложение не использует spring mvc, и conversionService может как-то быть зарегистрированным, и я этого не делал.
Наконец, я решил проблему с регистрацией настраиваемого конвертера с помощью редактора свойств. Эта документация может рассматриваться как ссылка:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html
Мне было бы очень интересно узнать, почему spring не нашел мои зарегистрированные пользовательские конвертеры в реестре conversionService (или, по крайней мере, почему spring не смотрел этот реестр, чтобы найти пользовательские конвертеры). У меня отсутствовала какая-либо конфигурация?
Ответ 2
Для тех, кто наткнулся на это сейчас через поиск Google или аналогичные 2+ года после того, как вопрос был первоначально отправлен, добавление конвертеров стало намного проще благодаря Java Config: WebMvcConfigurerAdapter
предоставляет метод addFormatters(FormatterRegistry)
, который можно использовать для указания дополнительных пользовательских преобразователей.
Ответ 3
Вы также можете добавить его динамически с помощью метода addConverter в свой класс DefaultConversionService-ish:
DefaultConversionService cs = new <YourClassThatInheritsFromDefaultConversionService or DefaultConversionService>();
cs.addConverter(new MyConverter());
Ответ 4
С пружиной> 4 больше нет необходимости реализовывать собственный производный от ConversionService. Инициализируйте его в аннотированном классе @Configuration следующим образом:
@Configuration
public class ConversionServiceProvider
{
@Autowired
private MyConverterImpl myConverter;
@Bean
public ConversionService getConversionService()
{
ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
bean.setConverters( getConverters() );
bean.afterPropertiesSet();
ConversionService object = bean.getObject();
return object;
}
private Set<Converter<?, ?>> getConverters()
{
Set<Converter<?, ?>> converters = new HashSet<Converter<?, ?>>();
converters.add( myConverter );
// add here more custom converters, either as spring bean references or directly instantiated
return converters;
}
}
Ответ 5
Вышел очень интересный способ сделать это в Stackoverflow - fooobar.com/questions/285574/...
Используя функцию, называемую Слияние коллекций, вы можете по существу сделать это:
<bean id="customConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" parent="conversionService">
<property name="converters">
<list merge="true">
<bean id="StringToLoggerConverter" class="com.citi.spring.converter.LoggerConverter" />
</list>
</property>
</bean>
Ответ 6
Этого достаточно, чтобы переопределить ConversionServiceFactoryBean.afterPropertiesSet() и установить для объекта ConversionService ваши конвертеры.
Пусть ваши конвертеры реализуют некоторый интерфейс, который позволяет установить объект ConversionService, скажем, ConversionServiceAware.
Единственная проблема - получить доступ к зарегистрированным конвертерам, поэтому вам также придется переопределить метод setConverters().
public class MyFormattingConversionServiceFactoryBean extends FormattingConversionServiceFactoryBean {
private Set<?> cachedConverters = new LinkedHashSet<>();
@Override
public void setConverters(Set<?> converters) {
super.setConverters(converters);
this.cachedConverters = new LinkedHashSet<>(converters);
}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
FormattingConversionService conversionService = getObject();
for (Object converter : cachedConverters) {
if (converter instanceof ConversionServiceAware) {
((ConversionServiceAware) converter).setConversionService(conversionService);
}
}
}
}
Ответ 7
напишите пользовательское conversionService
public class CustomerConversionServiceFactoryBean extends ConversionServiceFactoryBean {
List<Converter<Object, Object>> converters = new ArrayList<>();
public CustomerConversionServiceFactoryBean() {
super();
DefaultConversionService conversionservice = (DefaultConversionService) super.getObject();
for(int i=0;i<converters.size();i++){
conversionservice.addConverter(converters.get(i));
}
}
}
затем измените свой xml
<bean id="conversionService"
class="CustomerConversionServiceFactoryBean" >
<property name="converters" >
<list>
<bean class="CustomConverter" />
</list>
</property>
</bean>
Я думаю, это поможет вам...
Ответ 8
Этот вариант у меня работает.
Если вы используете конфигурацию Java, вы можете добавить свои конвертеры в существующие GenericConversionService
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html
Config methods may have an arbitrary name and any number of arguments; each of those arguments will be autowired with a matching bean in the Spring container. Bean property setter methods are effectively just a special case of such a general config method. Such config methods do not have to be public.
@Configuration
class MyConfig {
@Autowired
void conversionService(GenericConversionService genericConversionService) {
genericConversionService.addConverter(String.class, UUID.class, UUID::fromString);
genericConversionService.addConverter(String.class, DateTime.class, DateTime::parse);
genericConversionService.addConverter(String.class, EnumState.class, EnumState::valueOf);
}
}