我想根据从客户端传递的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() {
}
}
我希望根据传递的参数注入报表实例。任何帮助都会有很大的吸引力。提前致谢
答案 0 :(得分: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
的新bean和新的ReportType
枚举值一样简单。你可以在没有enum
并使用字符串(甚至可能是bean名称)的情况下离开,但是我发现强类型很有用。
最后的想法:Report
名字有点不幸。 Report
类表示(无状态?)某些逻辑(Strategy模式)的封装,而名称表明它封装了 value (数据)。我建议ReportGenerator
或其他。