2011-09-24 16 views
7

Quiero tener inyectar un bean basado en un parámetro de cadena pasado del cliente.Inyección condicional de bean

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() { 
    } 
} 

Quiero que se emita una instancia de informe en función del parámetro aprobado. Cualquier ayuda sería muy apreciada. Gracias de antemano

Respuesta

13

Uso Factory method patrón:

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

El informe tipo enum puede ser creado por la primavera cuando llama a un controlador con ?type=CSV:

class MyController{ 

    @Resource 
    private ReportFactory reportFactory; 

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

} 

Sin embargo ReportFactory es bastante torpe y requiere la modificación cada vez que agrega un nuevo tipo de informe. Si la lista de tipos de informes está corregida, está bien. Pero si va a añadir más y más tipos, esto es una implementación más robusta:

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 esta aplicación añadiendo nuevo tipo de informe es tan simple como añadir nuevo bean de implementación Report y un nuevo valor ReportType enumeración. Podrías escapar sin el enum y usar cadenas (tal vez incluso nombres de beans), sin embargo, creo que escribir con fuerza es beneficioso.


último pensamiento: Report nombre es un poco desafortunado. Report clase representa (sin estado?) Encapsulación de alguna lógica (patrón Strategy), mientras que el nombre sugiere que encapsula valor (datos). Sugeriría ReportGenerator o tal.

+0

Muchas gracias Tomasz ... probará esto. Voy a cambiar el nombre en consecuencia. –

+0

Funcionó como un amuleto..Muchas gracias –

+0

+1 por mostrar la opción escalable – DecafCoder

Cuestiones relacionadas