Conditional injection bean

I want to add 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 the instance of the instance to be introduced based on the passed parameter. Any help would be greatly expanded. thanks in advance

+7
source share
1 answer

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

The enum report type can be created by Spring when invoking your controller using ?type=CSV :

 class MyController{ @Resource private ReportFactory reportFactory; public HttpResponse getReport(@RequestParam("type") ReportType type){ reportFactory.forType(type); } } 

However, ReportFactory pretty awkward and needs to be changed every time you add a new report type. If the report list is displayed, if it is corrected, this is normal. 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 a new report type is as simple as adding a new bean for the Report implementation and a new ReportType enumeration ReportType . You can leave without enum and use strings (maybe even bean names), however I found that I am gaining a lot of usefulness.


One final thought: Report name is a bit unsuccessful. Report class represents (stagnant?) The encapsulation of some logic ( Strategy pattern, whereas the name assumes that it encapsulates the value (data). I would suggest ReportGenerator or such.

+13
source

All Articles