【问题标题】:select spring bean during runtime在运行时选择spring bean
【发布时间】:2013-09-27 08:27:30
【问题描述】:

我在选择应该注入的正确 spring bean 时遇到问题。 我需要一种方法来告诉 spring 容器注入什么 bean,这取决于对前一个类的调用。我在 xml 中完成所有 spring bean 接线。

我的问题:这可能吗?是否对实现有任何参考?

我创建了一些示例代码来说明我想要完成的工作。随意更改它,以便在运行时根据所选的 reportType 注入正确的 ReportHeader bean。

public enum ReportType{
    Credit,
    Annul   
}

public class ReportService {

    private ReportHeaderService reportHeaderService;
    private ReportType reportType;

    public ReportService (){}

    public setReportType(ReportType reportType){
        this.reportType = reportType;
    }

    public void setReportHeaderService(ReportHeaderService reportHeaderService){
        this.reportHeaderService = reportHeaderService;
    }

    private void generateHeader(){
        //i would like to call my service like this and have the correct bean injected to ReportHeader.
        reportHeaderService.generateHeader(reportType)
    }
}

public class ReportHeaderService {

    private ReportHeader reportHeader;

    //this will call the injected bean that needs to be selected accoring to the ReportType
    public void generateHeader(ReportType type){
        reportHeader.createHeader();
    }
}

public interface ReportHeader{
    public void createHeader();
}

public class CreditReportHeader implements ReportHeader{
    public void createHeader(){
        ..dostuff();
    }
}

public class AnnulReportHeader implements ReportHeader{
    public void createHeader(){
        ..dostuff();
    }
}

【问题讨论】:

    标签: java spring dependency-injection


    【解决方案1】:

    考虑将Map<ReportType, ReportHeader> 注入到 ReportHeaderService 中,这样 generateHeader 的工作方式如下:

    public class ReportHeaderService {
    
        private Map<ReportType, ReportHeader> reportHeaderMap;
    
        public void generateHeader(ReportType type){
            ReportHeader reportHeader = reportHeaderMap.get(type);
            if (reportHeader != null) {
                reportHeader.createHeader();
            }
        }
    }
    

    【讨论】:

    • 这当然是一个可行的解决方案,但我希望避免注入一个以上的 bean,因为我猜所有的 bean 都将被注入到地图中,而不仅仅是在调用 get 后加载地图?
    • 如果你希望它被延迟加载,你应该被允许将延迟加载代理而不是实际的 bean 注入到地图中。
    • 您可能想要研究的另一件事是装饰器模式:您可以创建一个 ReportHeader impl,它负责将 createHeader() 调用委派给正确的调用。当然,ReportType 需要是 createHeader() 的输入参数
    【解决方案2】:

    你可以定义一个ReportHeaderFactory,根据ReportType得到ReportHeader

    public class ReportHeaderFactory {
        private CreditReportHeader creditReportHeader;
        private AnnulReportHeader annulReportHeader;
    
        public ReportHeader getReportHeader(ReportType reportType) {
            switch (reportType) {
            case Credit:
                return creditReportHeader;
            case Annul:
                return annulReportHeader;
            default:
                throw new IllegalArgumentException("No Such Header");
            }
        }
    }
    

    使用ReportHeaderFactory 的实例重新定义ReportHeaderService

    public class ReportHeaderService {
    
        //private ReportHeader reportHeader;
        private ReportHeaderFactory headerFactory;
    
        //this will call the injected bean that needs to be selected accoring to the ReportType
        public void generateHeader(ReportType type){
            //reportHeader.createHeader();
            headerFactory.getReportHeader(type);
        }
    }
    

    当您在 xml 中进行所有 spring bean 接线时,您只需要在配置文件中创建以下条目:

        <bean id="ReportHeaderService" class="x.y.ReportHeaderService">
            <property name="headerFactory" ref="headerFactory" />
        </bean>
    
        <bean id="headerFactory" class="x.y.ReportHeaderFactory">
            <property name="creditReportHeader" ref="creditReportHeader" />
            <property name="annulReportHeader" ref="annulReportHeader" />
        </bean>
    
        <bean id="creditReportHeader" class="x.y.CreditReportHeaderImpl" />
        <bean id="annulReportHeader" class="x.y.AnnulReportHeaderImpl" />
    

    【讨论】:

    • 这当然是一个可行的解决方案,但我希望避免注入一个以上的 bean。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-14
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多