我正在尝试更改一些遗留代码以将 DI 与 Spring 框架结合使用。我有一个具体案例,我想知道哪种是最正确的实现方法。
这是一个java桌面应用程序。有一个 DataManager 接口(interface)用于查询/更改数据存储中的数据。目前只有一种使用 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 的方法。
我。仅在工厂中注入(inject)依赖项,不要更改任何其他代码。
这是新代码:
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 概念不熟悉,因此我将感谢每一个建议,这些建议将是正确的和“最佳实践”的解决方案。 非常感谢。
最佳答案
使用选项 3。
第一个选项会使您的代码无法测试。您将无法轻松模拟静态工厂方法以使其返回模拟 DataManager。
第二个选项将强制您让根类了解所有非根类的所有依赖项,以使代码可测试。
第三个选项实际上使用依赖注入(inject),其中每个 bean 只知道其直接依赖关系,并由 DI 容器注入(inject)。
关于java - 依赖项应该注入(inject)一次还是每个对象中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14687722/