2

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

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

我要求用 Spring DI 表示下面的代码片段并为MainFactoryTotalReport. 另外,我不想传递TotalReportnewInstance()方法。

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

1 回答 1

0

解决方案 1

FirstCSVConcrete实例化类型和通常的bean FirstXLSConcrete,即:

@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:更整洁;将aspectj与Spring一起使用

@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 魔法开始工作。对于带有@Configurable注解的类,@Autowired依赖会自动解析;即使实例是在弹簧容器之外创建的。

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

于 2013-05-27T07:30:18.310 回答