应该依赖注入一次或每个对象

时间:2013-02-04 13:24:38

标签: java spring design-patterns dependency-injection

我正在尝试更改一些遗留代码,以便在Spring框架中使用DI。我有一个具体案例,我想知道哪种方法最适合实施它。

这是一个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。

予。仅在工厂中注入依赖项,不要更改任何其他代码。

这是新代码:

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>

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

III。与II相同。但对于使用数据管理器的每个类,都要创建一个Spring bean定义,并使用Spring Ioc容器实例化每个这样的类。

由于我是DI概念的新手,我将非常感谢您提出的正确和“最佳实践”解决方案。 非常感谢提前。

3 个答案:

答案 0 :(得分:2)

使用选项3。

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

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

小心(因为你是新手),你不会在数据管理器中探索每个可用的课程!这是一个非常常见的错误,如果你没有充分地抽象出集中的职责,你会发现你正在配置有很多经理的课程。当你看到你正在这样做时,现在是退一步看看你的抽象和组件化的好时机。