Java – conditionally inject beans
I want to inject a bean based on the string parameter passed from the client
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() {
}
}
I want to inject report instances based on the parameters passed Any help would be very useful Thank you in advance
Solution
Use factory method mode:
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);
}
}
}
When you use? Type = when CSV calls the controller, spring can create an enumeration of report types:
class MyController{
@Resource
private ReportFactory reportFactory;
public HttpResponse getReport(@RequestParam("type") ReportType type){
reportFactory.forType(type);
}
}
However, reportfactory is very clumsy and needs to be modified every time a new report type is added If the list of report types is fixed, there is no problem But if you plan to add more and more types, this is a more powerful 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 a new report type is as simple as adding a new bean to implement report and a new reporttype enumeration value You can leave without enumerating and using strings (maybe even bean names), but I find strong typing useful
Finally, I thought: the name of the report is a little unfortunate Report class representation (stateless?) The encapsulation of some logic (strategy pattern), and the name indicates that it encapsulates values (data) I'll suggest report generator and so on
