有条件地注入豆

我想根据从客户端传递的String参数注入一个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() { } } 

我希望根据传递的参数注入报表实例。 任何帮助都会非常有用。 提前致谢

使用Factory方法模式:

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

当您使用?type=CSV调用控制器时,Spring可以创建报告类型enum

 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 reports; public Report forType(ReportType type) { for(Report report: reports) { if(report.supports(type)) { return report; } } throw new IllegalArgumentException("Unsupported type: " + type); } } 

通过此实现,添加新报告类型就像添加新bean实现Report和新的ReportType枚举值一样简单。 你可以在没有enum和使用字符串(甚至可能是bean名称)的情况下离开,但是我发现强类型很有用。


最后想到: Report名称有点不幸。 Report类表示(无状态?)某些逻辑( 策略模式)的封装,而名称表明它封装了 (数据)。 我会建议ReportGenerator等。