静态工厂依赖注入与外部依赖

时间:2013-05-26 18:01:27

标签: spring dependency-injection

我们如何在Spring上下文中创建bean以注入依赖项?

我可以通过指定MainFactory来创建factory-method = "newInstance",但是对于创建的实例,例如FirstCSVConcrete()FirstXLSConcrete()。我还需要注入TotalReport bean。那么,我们如何在Spring上下文中创建工厂时注入外部依赖项。

我要求使用Spring DI表示以下代码段并为MainFactoryTotalReport创建bean。另外,我不想将TotalReport传递给newInstance()方法。

public class MainFactory {
    private FirstInterface firstInterface;
    private MainFactory(String type){
        if(type.equalsIgnoreCase("CSV")){
            firstInterface = new FirstCSVConcrete();
        } else {
            firstInterface = new FirstXLSConcrete();
        }
    }
    public static MainFactory newInstance(String type){
        return new MainFactory(type);
    }
}

public class FirstCSVConcrete implements FirstInterface {
    TotalReport totalReport;
}

public class FirstXLSConcrete implements FirstInterface {
    TotalReport totalReport;
}

1 个答案:

答案 0 :(得分:0)

解决方案1 ​​

通常实例化FirstCSVConcreteFirstXLSConcrete类型的bean,即:

@Component
public class FirstCSVConcrete implements FirstInterface { 
    @Autowired
    private TotalReport totalReport;
}

同样适用于FirstXLSConcrete

现在,按如下方式设置MainFactory

public class MainFactory {

    @Autowired
    private FirstCSVConcrete firstCSVConcrete;

    @Autowired
    private FirstXLSConcrete firstXLSConcrete;


    private String type;

    public static MainFactory newInstance(String type){
        return new MainFactory(type);
    }

    private MainFactory(String type) {
        this.type = type;
    }


    private FirstInterface selectedFirstInterface = null;
    public FirstInterface getFirstInterface() {
        if(selectedFirstInterface == null) {
            selectedFirstInterface = selectFirstInterfaceForType(type);
        }
        return selectedFirstInterface;
    }

    private FirstInterface selectFirstInterfaceForType(String type) {
        if("CSV".equalsIgnoreCase(type)) {
            return firstCSVConcrete;
        }
        return firstXLSConcrete;
    }
}

Spring无法将依赖项注入您自己实例化的对象中。所以,你必须采用这种方法,或者其中的一种方法。

解决方案2:更加整洁;使用带有Spring的aspectj

@Component
public class TotalReport {
    ...
}

@Configurable
public class FirstXLSConcrete implements FirstInterface {

    @Autowired
    private TotalReport totalReport;

    ...
}

@Configurable
public class FirstCSVConcrete implements FirstInterface {
    @Autowired
    private TotalReport totalReport;

}

public class MainFactory {

    private FirstInterface firstInterface;

    private MainFactory(String type) {
        if (type.equalsIgnoreCase("CSV")) {
            firstInterface = new FirstCSVConcrete();
        } else {
            firstInterface = new FirstXLSConcrete();
        }
        System.out.println(firstInterface.getTotalReport());
    }

    public static MainFactory newInstance(String type) {
        return new MainFactory(type);
    }

}

在您的应用程序上下文配置文件中声明以下内容:

<context:load-time-weaver />
<context:spring-configured />

在应用程序的context.xml目录中创建META-INF,并将以下内容放入其中。

<Context path="/youWebAppName">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
        useSystemClassLoaderAsParent="false"/>
</Context>

将Spring的spring-tomcat-weaver.jar(可能名为org.springframework.instrument.tomcat-<version>.jar)放在tomcat安装的lib目录中,瞧,aspectj magic开始工作。对于使用@Configurable注释进行注释的类,@Autowired依赖项将自动解析;即使实例是在弹簧容器外创建的。

我猜答案已经变得很长了。如果您想了解更多详情,请点击using aspectj with Spring链接。还有几个配置选项。把自己弄出来。