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

我希望根据传递的参数注入报告实例。任何帮助都将非常感激。提前感谢

使用工厂方法模式

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

在这个实现中,添加新的报告类型就像添加新的bean实现Report和一个新的ReportType enum值一样简单。您可以不使用enum而使用字符串(甚至可能是bean名称),但是我发现强类型是有益的。


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

最新更新