I want to have inject a bean based on a String parameter passed from client.
public interface Report {
generateFile();
}
public class ExcelReport extends Report {
//implementation for generateFile
}
public class CSVReport extends Report {
//implementation for generateFile
}
class MyCo开发者_如何学编程ntroller{
Report report;
public HttpResponse getReport() {
}
}
I want report instance to be injected based on the parameter passed. Any help would be greatly appretiated. Thanks in advance
Use Factory method pattern:
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);
}
}
}
The report type enum
can be created by Spring when you call your controller with ?type=CSV
:
class MyController{
@Resource
private ReportFactory reportFactory;
public HttpResponse getReport(@RequestParam("type") ReportType type){
reportFactory.forType(type);
}
}
However ReportFactory
is pretty clumsy and requires modification every time you add new report type. If the report types list if fixed it is fine. But if you plan to add more and more types, this is a more robust implementation:
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);
}
}
With this implementation adding new report type is as simple as adding new bean implementing Report
and a new ReportType
enum value. You could get away without the enum
and using strings (maybe even bean names), however I found strongly typing beneficial.
Last thought: Report
name is a bit unfortunate. Report
class represents (stateless?) encapsulation of some logic (Strategy pattern), whereas the name suggests it encapsulates value (data). I would suggest ReportGenerator
or such.
精彩评论