【问题标题】:Conditional injection of beanbean的条件注入
【发布时间】:2011-11-24 03:44:30
【问题描述】:

我想根据从客户端传递的字符串参数注入一个 bean。

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

我希望根据传递的参数注入报表实例。任何帮助将不胜感激。提前致谢

【问题讨论】:

    标签: java spring dependency-injection


    【解决方案1】:

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

    当你用?type=CSV调用你的控制器时,Spring可以创建报告类型enum

    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 的新bean 和一个新的ReportType 枚举值一样简单。你可以不用enum 并使用字符串(甚至可能是 bean 名称),但我发现强类型输入很有用。


    最后的想法:Report 名字有点不幸。 Report 类表示(无状态?)封装一些逻辑(Strategy 模式),而顾名思义,它封装了 value(数据)。我建议ReportGenerator 之类的。

    【讨论】:

    • 非常感谢 Tomasz...会试试这个。我会相应地更改名称。
    • 工作就像一个魅力..非常感谢你
    猜你喜欢
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    相关资源
    最近更新 更多