2011-12-01 17 views
8

Utilizzo di Spring mvc-3. Sto scrivendo un convertitore personalizzato che richiede l'accesso ad altri convertitori registrati su un servizio di conversione.iniezione di ConversionService in un convertitore personalizzato

Come posso realizzare questo? Ho provato a scrivere il mio convertitore personalizzata come:

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

    } 

    } 

E ho registrato il mio convertitore personalizzato tramite applicationContext.xml

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

Tuttavia, la primavera si rifiuta di iniettare il servizio nel mio CustomConverter (la sua sempre null). Come posso realizzare questo?

Grazie!

risposta

5

Ho usato qualcosa di simile recentemente per risolvere questo problema. Utilizzare una fabbrica personalizzato:

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

che è dichiarato in questo modo:

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

Sono giunto alla stessa conclusione! Grazie. – Ajay

+1

Il problema con questa soluzione è che MyCustomConverter non è gestito dal contenitore della molla – Gleeb

6

che ho incontrato lo stesso problema. C'è un issue SPR-6415 in Spring JIRA che copre questo problema. Ho dato qui la mia soluzione basata sulla discussione in questo numero. È lo stesso principio della risposta di @nmervaillie ma non è necessario implementare il proprio 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

problema principale (che ho incontrato) è quando si utilizza per la costruzione di ConversionServiceFactoryBeanconversion service che include convertitori che utilizzano conversion service così è che si ottiene l'errore a causa di ConversionServiceFactoryBean.getObject metodo che fornisce istanza di conversion service viene chiamato prima a ConversionServiceFactoryBean.afterPropertiesSet dove viene effettivamente creata l'istanza del servizio di conversione.

Quindi, Per evitare questo comportamento, basta per creare conversion service prima ConversionServiceFactoryBean.getObject si chiama. L'ho realizzato in un costruttore di classe che estende ConversionServiceFactoryBean. Esempio:

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 
    } 

di quanto si possa utilizzare convertitori che utilizza conversion service pure. Spero che aiuti.

0

Ho risolto questo problema nell'applicazione centrica di Spring.I componenti principali di questa soluzione sono:

  • dichiarano implementazioni Converter i fagioli molla
  • utilizzando @Lazy dalla primavera-contesto sui punti di iniezione nei convertitori
  • inietti tutti i convertitori scoperto in una ConversionServiceFactoryBean

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

e Configurazione:

@Configuration 
public class ConversionServiceConfig { 

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

...

Le annotazioni @Lazy aggira il problema uovo-gallina, iniettando un proxy e ritardare la risoluzione del chicco conversionservice fino a quando non viene effettivamente utilizzato in tal modo.

Problemi correlati