Условное введение бобов - PullRequest
7 голосов
/ 24 сентября 2011

Я хочу внедрить bean-компонент на основе параметра String, переданного от клиента.

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

Я хочу, чтобы экземпляр отчета вводился на основе переданного параметра. Любая помощь будет высоко оценена. Заранее спасибо

1 Ответ

13 голосов
/ 24 сентября 2011

Использование Заводской метод шаблон:

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

В этой реализации добавить новый тип отчета так же просто, как добавить новый компонент, реализующий Report и новое значение перечисления ReportType. Вы можете обойтись без enum и использования строк (возможно, даже имен бинов), однако я считаю, что печатать очень полезно.


Последняя мысль: Report имя немного неудачно. Класс Report представляет (без сохранения состояния?) Инкапсуляцию некоторой логики (шаблон Стратегия ), тогда как название предполагает, что он инкапсулирует значение (данные). Я бы предложил ReportGenerator или такой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...