将ConversionService注入自定义Converter

时间:2011-12-01 04:03:23

标签: java spring spring-mvc

使用Spring mvc-3。我正在编写一个自定义转换器,需要访问注册到ConversionService的其他转换器。

我怎样才能做到这一点?我尝试将自定义转换器编写为:

  class CustomConverter<X, Y>{
     @Autowired ConversionService service;
     //+getter & setters of service

     public Y convert(X input){
          // I need access to service to lookup simple conversions such as
          // String array to Long array etc..

     }

  }

我通过applicationContext.xml

注册了自定义转换器
  <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
     <property name = "converters">
         <list>
            <bean class="CustomConverter"/>
         </list>
     </property>
  </bean>

但是,spring拒绝将服务注入我的CustomConverter(它总是为null)。我怎么能做到这一点?

谢谢!

3 个答案:

答案 0 :(得分:8)

我遇到过同样的问题。 Spring JIRA中有一个issue SPR-6415来解决这个问题。我根据本期的讨论给出了我的解决方案。这与@nmervaillie的答案相同,但您不必实现自己的ConversionServiceFactoryBean

/**
 * Base class of @{code Converter} that need to use {@code ConversionService}.
 * Instances of implementing classes must be spring-managed to inject ConversionService.
 * 
 * @author Michal Kreuzman
 */
public abstract class CoversionServiceAwareConverter<S, T> implements Converter<S, T> {

  @Inject
  private ConversionService conversionService;

  protected ConversionService conversionService() {
    return conversionService;
  }

  /**
   * Add this converter to {@code ConverterRegistry}.
   */
  @SuppressWarnings("unused")
  @PostConstruct
  private void register() {
    if (conversionService instanceof ConverterRegistry) {
      ((ConverterRegistry) conversionService).addConverter(this);
    } else {
      throw new IllegalStateException("Can't register Converter to ConverterRegistry");
    }
  }
}

@Component
public class SampleConverter extends CoversionServiceAwareConverter<Object, Object> {

    @Override
    public String convert(Object source) {
        ConversionService conversionService = conversionService();

        // Use conversionService and convert
    }
}

答案 1 :(得分:7)

我最近用过这样的东西来解决这个问题。 使用自定义工厂:

public class MyConversionServiceFactoryBean extends ConversionServiceFactoryBean {

    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        ConversionService conversionService = getObject();
        ConverterRegistry registry = (ConverterRegistry) conversionService;
        // register converters that need a nested conversion service
        registry.addConverter(new MyCustomConverter(conversionService));
    }
}

声明如下:

<bean id="conversionService"
    class="com.company.MyConversionServiceFactoryBean">
    <property name="converters">
        <list>
            ... declare standard converters here ...
        </list>
    </property>
</bean>

答案 2 :(得分:0)

主要问题(我遇到过的)是当你使用ConversionServiceFactoryBean构建conversion service时,其中包含使用conversion service的转换器,因为{{1}会导致错误在ConversionServiceFactoryBean.getObject之前调用提供conversion service实例的方法,其中实际创建了转换服务实例。

因此,以避免此行为,您只需要ConversionServiceFactoryBean.afterPropertiesSet之前创建conversion service 。我已经在扩展ConversionServiceFactoryBean.getObject的类的构造函数中创建了它。 例如:

ConversionServiceFactoryBean

您也可以使用使用 try { Field serviceField = ConversionServiceFactoryBean.class.getDeclaredField("conversionService"); conversionServiceField.setAccessible(true); conversionServiceField.set(this, createConversionService()); } catch (NoSuchFieldException | IllegalAccessException fieldAccessError) { fieldAccessError.printStackTrace(); //or do some log output here, it's up to you } 的转换器。 希望它有所帮助。