2011-09-24 36 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