我有一个复杂的对象需要嵌套的转换器说我有B类,包括A的实例。
class A {
....
}
class B {
A a;
....
}
我为A编写了一个转换器,转换为其他类别的“AA”。 现在我需要编写一个转换器,将B转换为其他类。由于B中有A。我需要将A转换为另一个“AA”。 我正在使用转换器模式。 并看到这个ans: injecting ConversionService into a custom Converter 有比这更好的方法吗?我宁愿不在自定义工厂类中初始化转换器。
答案 0 :(得分:2)
你可以这样做。创建转换器服务并注入一组您声明的转换器bean。在某些情况下,转换器可能需要访问converterService。您可以使用@Lazy注释来绕过循环引用。如果存在其他转换服务,您可能需要@Primary让spring知道您声明的converterService应该优先注入。在某些情况下,使转换器可以访问转换服务很有用。通过将转换服务从当前转换器内部分配到正确的转换器,可以保持松耦合。此外,这使您可以重复使用其他转换器中常见的转换器,从而消除代码重复。
/**
* @author vsutskever 3/22/18
**/
@Configuration
public class ConverterConfig {
/**
* Circular reference. This beans depends on Conversion service. Using @Lazy to resolve.
* @param service
* @return
*/
@Bean
public Converter dispositionMessageConverter(
@Lazy ConversionService service){
return new DispositionMessageRequestToOutgoingMessage(service);
}
/**
* Circular reference. This beans depends on Conversion service. Using @Lazy to resolve.
* @param service
* @return
*/
@Bean
public Converter contentMessageRequestToOutgoingMessageConverter(
@Lazy ConversionService service){
return new ContentMessageRequestToOutgoingMessageConverter(service);
}
@Bean
public Converter incomingRcsMessageToBaseMessageConverter(){
return new IncomingRcsMessageToBaseMessageConverter();
}
@Bean
public Converter contactToAddressConverter(){
return new ContactToAddressConverter();
}
@Bean
@Primary
public ConversionService conversionService(List<Converter> converters){
ConversionServiceFactoryBean factory = new ConversionServiceFactoryBean();
factory.setConverters(new HashSet<>(converters));
factory.afterPropertiesSet();
return factory.getObject();
}
}
答案 1 :(得分:1)
使用BB类:
class BB {
....
AA aa;
....
}
您可以这样做:
public BB convert(B b) {
BB bb = new BB();
bb.aa = new AToAAConverter().convert(b.a);
....
您仍然可以在AToAAConverter
注册ConversionServiceFactoryBean
。
答案 2 :(得分:1)
我找到了一个无需编写自定义conversionService的解决方案,使用@Lazy批注解决了循环依赖性。
Configuration
类,如:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
@Lazy
private ConversionService mConversionService;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(aConverter());
registry.addConverter(bConverter());
}
@Bean
public AConverter aConverter() {
return new AConverter();
}
@Bean
public BConverter bConverter() {
return new BConverter(mConversionService);
}
}
AConverter
和BConverter
都实现org.springframework.core.convert.converter.Converter<S,T>
,因为AConverter
将类A
转换为AA
并且BConverter
转换类{ {1}}转到另一个包含B
的类。
更新
在A
构造函数中注入ConversionService
更好,可以避免字段注入:
WebConfig
答案 3 :(得分:0)
假设您要将B
转换为BB
,为什么不将Converter<A, AA>
注入BToBbConverter
?
@Component
public class BToBbConverter implements Converter<B, BB> {
private final Converter<A, AA> aToAaConverter;
public BToBbConverter(Converter<A, AA> aToAaConverter) {
this.aToAaConverter = aToAaConverter;
}
@Nullable
@Override
public BB convert(B source) {
// use aToAaConverter here
}
}
答案 4 :(得分:0)
我一直在做类似的事情(使用Spring 3.1.1),这对Spring来说是很新的东西,但是经过反复试验,这对我来说很有效。它支持嵌套转换器,转换器使用spring注释,而不必在@Configuration类中进行设置。
------ConversionFactoryBean.java-------
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Component;
@Component
@Qualifier("conversionService")
public class ConversionFactoryBean extends ConversionServiceFactoryBean {
// spring will inject beans by type
@Autowired
public Set <CustomConverter<?, ?>> customConverters;
@Override
public void afterPropertiesSet() {
// Set the custom converters (default converters will be handled by parent).
setConverters(customConverters);
// registers the custom converters
super.afterPropertiesSet();
// set the conversionService on the converters
final ConversionService conversionService = getObject();
for (Object converter : customConverters) {
((CustomConverter<?, ?>) converter).setConversionService(conversionService);
}
}
}
------CustomConverter.java-------
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
/**
* Base class of converters, providing access to conversionservice.
* @param <S> the source object to convert, which must be an instance of S
* @param <T> the converted object, which must be an instance of T
*/
public abstract class CustomConverter<S, T> implements Converter<S, T> {
private ConversionService conversionService;
/**
* constructor
*/
public CustomConverter() {
super();
}
public ConversionService getConversionService() {
return conversionService;
}
public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService;
}
}
------ConsumerSummaryConverter.java-------
import org.springframework.stereotype.Component;
@Component
public class ConsumerSummaryConverter
extends CustomConverter <CustomerDetail, ConsumerSummary> {
public ConsumerSummaryConverter() {
super();
}
@Override
public ConsumerSummary convert(CustomerDetail source) {
// use nested converter
Individual ind = getConversionService().convert(source, Individual.class);
// do rest of conversion...
}
}
-----ServiceConfig.java------
@Configuration
@ComponentScan({"uk.co.my.custom.converter"})
public class ServiceConfig { // empty at the moment}