2011-12-01 98 views
8

使用Spring mvc-3。我正在编写一个自定义转换器,它需要访问注册到ConversionService的其他转换器。将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> 

然而,春天拒绝服务注入到我的CustomConverter(其始终为空)。我怎样才能做到这一点?

谢谢!

回答

5

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

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> 
+0

我得出同样的结论!谢谢。 – Ajay

+1

这个解决方案的问题是MyCustomConverter不是由spring容器管理的 – Gleeb

6

我也碰到过同样的问题。在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 
    } 
} 
0

主要问题(我以前遇到过)是当您使用ConversionServiceFactoryBean构建conversion service包括使用转换器conversion service也就是你,因为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 
    } 

比你可以使用使用conversion service以及转换器。 希望它有帮助。

0

我在spring-ws中心应用程序中解决了这个问题。这个解决方案的主要组成部分是:

  • 声明转换器实施方式中为弹簧豆
  • 在ConversionServiceFactoryBean
在转换器使用从@Lazy在注入点弹簧上下文
  • 注入所有发现的转换器

    SampleConverter

    @Component 
    public class SampleConverter implements Converter<Source, Target> { 
    
    private ConversionService conversionService; 
    
        @Inject 
        @Lazy 
        public SampleConverter(ConversionService conversionService){ 
         this.conversionService = conversionService; 
        } 
    
        @Override 
        public Target convert(Source source){ 
         Target target = new Target(); 
         ... 
        target.setTargetDetails(conversionService.convert(source.getSourceDetails, TargetDetails.class); 
        ... 
    

    和配置:

    @Configuration 
    public class ConversionServiceConfig { 
    
        @Bean 
        public ConversionService conversionService(Set<Converter<?,?>> converters){ 
         ConversionServiceFactoryBean csfb = new ConversionServiceFactoryBean(); 
         csfb.setConverters(converters); 
         csfb.afterPropertiesSet(); 
         return csfb.getObject(); 
        } 
    

    ...

    的@Lazy注释注入的代理,并从而延缓conversionservice豆的分辨率,直到它真正用于绕开蛋鸡问题。