【问题标题】:static factory Dependency Injection with external dependency具有外部依赖的静态工厂依赖注入
【发布时间】:2013-05-26 18:01:27
【问题描述】:

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

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

我要求用 Spring DI 表示下面的代码 sn-p 并为 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;
}

【问题讨论】:

    标签: spring dependency-injection


    【解决方案1】:

    解决方案 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 />
    

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

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

    将 Spring 的 spring-tomcat-weaver.jar(可能命名为 org.springframework.instrument.tomcat-&lt;version&gt;.jar)放在你的 tomcat 安装的 lib 目录中,瞧,aspectj 魔法开始起作用了。对于带有@Configurable注解的类,@Autowired的依赖会自动解析;即使实例是在 spring-container 之外创建的。

    我想答案现在已经变得很长了。如果您想了解更多详细信息,这里是using aspectj with Spring 的链接。还有几个配置选项。把自己打晕。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-09
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多