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