2011-09-24 35 views
7

我想根據從客戶端傳遞來的String參數注入bean。有條件地注入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() { 
    } 
} 

我想根據傳遞參數注入報告實例。任何幫助都會非常令人滿意。在此先感謝

回答

13

使用Factory method模式:

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

enum可以由Spring當你與?type=CSV打電話給你的控制器來創建報告:

class MyController{ 

    @Resource 
    private ReportFactory reportFactory; 

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

} 

然而ReportFactory是相當笨拙而需要修改每次添加新的報告類型。如果報告類型列表已修復,那麼很好。但是,如果您打算添加的種類越來越多,這是一個比較穩健的實現:

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

有了這個實現添加新的報告類型添加新豆實現Report和新ReportType枚舉值一樣簡單。如果沒有enum並使用字符串(甚至可能是bean名稱),你可能會離開,但是我發現強類型有益。


最後想到:Report名字有點不幸。 Report類表示一些邏輯(Strategy模式)的封裝(無狀態?),而名稱表明它封裝了(數據)。我會建議ReportGenerator或這樣的。

+0

非常感謝你Tomasz ...會試試這個。我會相應地更改名稱。 –

+0

工作就像一個魅力..非常感謝 –

+0

+1顯示可擴展選項 – DecafCoder