2011-12-01 27 views
8

Spring mvc-3'ü kullanma. Bir ConversionService'ye kayıtlı diğer Dönüştürücülere erişmesi gereken özel bir Dönüştürücü yazıyorum.enjekte etme

Bunu nasıl yapabilirim? (Onun her zaman boş)

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.. 

    } 

    } 

Ve

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <property name = "converters"> 
     <list> 
      <bean class="CustomConverter"/> 
     </list> 
    </property> 
    </bean> 

Ancak, bahar benim CustomConverter içine hizmetini enjekte reddeden applicationContext.xml

aracılığıyla benim özel dönüştürücü kayıtlı: Ben benim özel dönüştürücü yazmaya çalıştı. Bunu nasıl başarabilirim?

Teşekkür ederiz!

cevap

5

Bu sorunu çözmek için son zamanlarda böyle bir şey kullandım. Özel bir fabrika kullanın:

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)); 
    } 
} 

böyle ilan edilir:

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

Aynı sonuca vardım! Teşekkür ederim. – Ajay

+1

Bu çözümdeki sorun, MyCustomConverter'ın yaylı kapsayıcı tarafından yönetilmemesidir. – Gleeb

6

Ben aynı sorunu rastlamak var. Bu sorunu kapsayan Spring JIRA'da bir issue SPR-6415 var. Burada bu konudaki tartışmaya dayanarak çözümümüzü verdim. @nmervaillie'nin cevabı gibi aynı prensiptir, ancak kendi ConversionServiceFactoryBean'u uygulamanız gerekmez.

/** 
* 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 
    } 
} 
conversion service yanı yüzünden conversion service örneği önce çağrılan sağlar ConversionServiceFactoryBean.getObject yöntemin hata alıyorum olmasıdır
0

Ana sorun, (i karşılaştı ettik) kullandığınız dönüştürücüler içerir conversion service oluşturmak için ConversionServiceFactoryBean kullandığınızda ise Bu dönüşüm hizmeti örneğinin gerçekte oluşturulduğu ConversionServiceFactoryBean.afterPropertiesSet.

Yani, sadece denir conversion service önce ConversionServiceFactoryBean.getObject oluşturmak için gerek Bu davranışı önlemek için. ConversionServiceFactoryBean'u genişleten bir sınıf kurucusunda yaptım. Örnek:

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 
    } 

siz de conversion service kullandığı dönüştürücüler kullanabilirsiniz daha. Umut eder.

0

Bu sorunu ilkbahar-merkezli uygulamada çözdüm.Bu çözeltilerin ana bileşenleri şunlardır: bir ConversionServiceFactoryBean dönüştürücüleri enjeksiyon noktalarında yay bağlamda tüm tespit dönüştürücüler

  • Inject @Lazy kullanılarak yay fasulye
  • olarak

    • ilan Dönüştürücü uygulamaları

      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); 
          ... 
      

      ve Yapılandırma:

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

      ...

      @Lazy ek açıklamalar gerçekten kullanılıncaya kadar conversionservice fasulye çözünürlüğünü geciktirmek ve böylece bir proxy enjekte tarafından yumurta tavuk problemi aşılmaktadır.

  • İlgili konular