1

我有一个复杂的对象,需要嵌套的转换器说我有包含 A 实例的 B 类。

 class A {
    ....
   }

   class B {
    A a;
    ....
   }

我为 A 编写了一个转换器,它可以转换为其他类,比如“AA”。现在我需要编写一个转换器,将 B 也转换为其他类。因为B里面有A。我需要将 A 转换为另一个东西“AA”。我正在使用转换器模式。并看到了这个答案: 将 ConversionService 注入自定义 Converter 有没有比这更好的方法?我不希望在自定义工厂类中初始化转换器。

4

5 回答 5

3

找到了不写自定义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将类转换AAA并将类BConverter转换B为其中包含的另一个类A

更新

ConversionService在构造函数中注入WebConfig更好,可以避免字段注入:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final ConversionService mConversionService;

    @Autowired
    public WebConfig(@Lazy ConversionService conversionService) {
        mConversionService = conversionService;
    }
}
于 2018-09-11T06:26:05.477 回答
2

与 BB 类一样:

class BB {
  ....
  AA aa;
  ....
}

你可以简单地做:

public BB convert(B b) {

  BB bb = new BB();
  bb.aa = new AToAAConverter().convert(b.a);
  ....

您仍然可以AToAAConverterConversionServiceFactoryBean.

于 2013-06-27T08:12:18.190 回答
2

你可以做这样的事情。创建一个转换器服务并注入一组您声明的转换器 bean。在某些情况下,您的转换器可能需要访问 converterService。您可以使用 @Lazy 注释绕过循环引用。您可能需要@Primary 让spring 知道如果存在其他conversionServices,您声明的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();
  }

}
于 2018-03-22T20:06:41.063 回答
1

我一直在做类似的事情(使用 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}
于 2019-02-21T11:05:43.630 回答
0

假设你想转换B成为什么BBConverter<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
  }
}
于 2018-12-03T20:43:25.003 回答