2011-09-24 11 views
7

Voglio iniettare un bean basato su un parametro String passato dal client.Iniezione condizionale di fagiolo

public interface Report { 
    generateFile(); 
} 

public class ExcelReport extends Report { 
    //implementation for generateFile 
} 

public class CSVReport extends Report { 
    //implementation for generateFile 
} 

class MyController{ 
    Report report; 
    public HttpResponse getReport() { 
    } 
} 

Desidero eseguire l'iniezione dell'istanza del report in base al parametro passato. Qualsiasi aiuto sarebbe molto apprezzato. Grazie in anticipo

risposta

13

Uso Factory method modello:

public enum ReportType {EXCEL, CSV}; 

@Service 
public class ReportFactory { 

    @Resource 
    private ExcelReport excelReport; 

    @Resource 
    private CSVReport csvReport 

    public Report forType(ReportType type) { 
     switch(type) { 
      case EXCEL: return excelReport; 
      case CSV: return csvReport; 
      default: 
       throw new IllegalArgumentException(type); 
     } 
    } 
} 

Il rapporto tipo enum può essere creato entro la primavera quando si chiama il controller con ?type=CSV:

class MyController{ 

    @Resource 
    private ReportFactory reportFactory; 

    public HttpResponse getReport(@RequestParam("type") ReportType type){ 
     reportFactory.forType(type); 
    } 

} 

Tuttavia ReportFactory è piuttosto goffo e richiede la modifica ogni volta che aggiungi un nuovo tipo di rapporto. Se il rapporto elenca i tipi, se risolto, va bene. Ma se si prevede di aggiungere più e più tipi, questa è un'implementazione più robusto:

public interface Report { 
    void generateFile(); 
    boolean supports(ReportType type); 
} 

public class ExcelReport extends Report { 
    publiv boolean support(ReportType type) { 
     return type == ReportType.EXCEL; 
    } 
    //... 
} 

@Service 
public class ReportFactory { 

    @Resource 
    private List<Report> reports; 

    public Report forType(ReportType type) { 
     for(Report report: reports) { 
      if(report.supports(type)) { 
       return report; 
      } 
     } 
     throw new IllegalArgumentException("Unsupported type: " + type); 
    } 
} 

Con questa implementazione aggiungendo nuovo tipo di report è semplice come l'aggiunta di nuovo bean attuazione Report e un nuovo valore ReportType enum. Potresti andare via senza lo enum e usando le stringhe (forse anche i nomi dei bean), tuttavia ho trovato che la tipizzazione era vantaggiosa.


Ultimo pensiero: Report nome è un po 'sfortunato. La classe Report rappresenta l'incapsulamento (stateless?) Di qualche logica (modello Strategy), mentre il nome suggerisce che incorpora il valore (dati). Suggerirei ReportGenerator o simile.

+0

Grazie mille Tomasz ... ci proveremo. Cambierò il nome di conseguenza. –

+0

Ha funzionato come un fascino..Grazie mille –

+0

+1 per mostrare l'opzione scalabile – DecafCoder

Problemi correlati