2

我正在尝试更改一些遗留代码以将 DI 与 Spring 框架一起使用。我有一个具体的案例,我想知道哪个是最合适的实现方式。

它是一个java桌面应用程序。有一个 DataManager 接口用于从数据存储中查询/更改数据。目前只有一种实现使用 XML 文件进行存储,但将来可以添加 SQL 实现。同样对于单元测试,我可能需要模拟它。

目前,需要数据管理器的每个代码和平都通过使用工厂来检索它。这是工厂的源代码:

public class DataManagerFactory   
{  
    private static DataManagerIfc dataManager;

    public static DataManagerIfc getInstance()
    {
        // Let assume synchronization is not needed
        if(dataManager == null)
            dataManager = new XMLFileDataManager();

        return dataManager;
    }
}

现在我看到了 3 种将应用程序更改为使用 DI 和 Spring 的方法。

I. 只在工厂中注入依赖,不要更改任何其他代码。

这是新代码:

public class DataManagerFactory  
{
    private DataManagerIfc dataManager;

    public DataManagerFactory(DataManagerIfc dataManager)
    {
        this.dataManager = dataManager;
    }

    public DataManagerIfc getDataManager()
    {
        return dataManager;
    }

    public static DataManagerIfc getInstance()
    {
        return getFactoryInstance().getDataManager();
    }

    public static DataManagerFactory getFactoryInstance()
    {
        ApplicationContext context =
                    new ClassPathXmlApplicationContext(new String[] {"com/mypackage/SpringConfig.xml"});

        return context.getBean(DataManagerFactory.class);
    }
}

以及带有 bean 描述的 XML:

<bean id="dataManagerFactory"
            class="com.mypackage.DataManagerFactory">
    <constructor-arg ref="xmlFileDataManager"/>
</bean>

<bean id="xmlFileDataManager"
    class="com.mypackage.datamanagers.xmlfiledatamanager.XMLFileDataManager">
</bean>

二、更改使用数据管理器的每个类,使其通过构造函数并将其存储为类变量。仅为创建链开始的“根”类创建 Spring bean 定义。

三、同Ⅱ。但是对于每个使用数据管理器的类,创建一个 Spring bean 定义并使用 Spring Ioc 容器实例化每个这样的类。

由于我是 DI 概念的新手,我会很感激每一个建议,什么是正确的和“最佳实践”的解决方案。提前谢谢了。

4

3 回答 3

2

使用选项 3。

第一个选项使您的代码无法测试。您将无法轻松地模拟静态工厂方法以使其返回模拟 DataManager。

第二个选项将强制您让根类知道所有非根类的所有依赖项,以使代码可测试。

第三个选项真正使用依赖注入,每个 bean 只知道它的直接依赖关系,并由 DI 容器注入。

于 2013-02-04T13:31:18.887 回答
0

嗯...你为什么首先写工厂?Spring 并不是为了让你改变你编写代码的方式(不仅仅是为了适应 Spring),所以保持工厂是正确的,因为它使用了众所周知的模式。将依赖项注入工厂将保留该行为。

于 2013-02-04T13:30:36.097 回答
0

选项 3 是正确的路线。通过使用这样的配置,您可以有效地获取配置的组件并在配置中使用它们,一切都会按预期工作。

根据经验,我希望调用 Spring 来实例化应用程序上下文并获取顶级 bean。我不希望重复调用 Spring 框架来获取多个 bean。一切都应该以正确的级别注入以反映责任等。

请注意(因为您是新手)不要在数据管理器中深入了解每个可用的课程!这是一个很常见的错误,如果你没有充分抽象和集中职责,你会发现你正在配置有很多管理器的类。当你看到你正在做这件事时,现在是退后一步,看看你的抽象和组件化的好时机。

于 2013-02-04T13:53:07.470 回答