Java Spring依赖注入解决了什么问题?
请参见此问题的顶部答案: 我不知道问题是什么,为什么Springs的解决方案将指定要在XML文件中使用的接口实现(或使用注释)比简单地用一行代码实例化正确的接口要好 编辑:正如我在一篇评论中所写的那样,我真诚地试图理解它的好处。我想了解为什么Spring很有用。我不是在提倡不使用Spring,也不是在试图提供不使用Spring的理由,而是在寻找理由并试图理解为什么应该使用Spring。这篇文章的目的不是鼓励辩论,而是提供直截了当的技术性答案。我现在选择最短和最具说明性的答案作为正确答案。我必须说,我有点惊讶这个问题已经结束了 我不知道问题出在哪里 问题主要在于如何在运行时或通过配置文件以友好方式交换实现 为什么Springs的解决方案会指定 在XML文件中使用的接口比简单地使用 代码行实例化正确的接口 这更好,因为可以调整XML文件,而无需重新编译和重新部署整个应用程序 这是关于DI最好的文章之一,您可能想看看:Java Spring依赖注入解决了什么问题?,java,spring,dependency-injection,inversion-of-control,Java,Spring,Dependency Injection,Inversion Of Control,请参见此问题的顶部答案: 我不知道问题是什么,为什么Springs的解决方案将指定要在XML文件中使用的接口实现(或使用注释)比简单地用一行代码实例化正确的接口要好 编辑:正如我在一篇评论中所写的那样,我真诚地试图理解它的好处。我想了解为什么Spring很有用。我不是在提倡不使用Spring,也不是在试图提供不使用Spring的理由,而是在寻找理由并试图理解为什么应该使用Spring。这篇文章的目的不是鼓励辩论,而是提供直截了当的技术性答案。我现在选择最短和最具说明性的答案作为正确答案。我必须说
如果A类使用B类,DI负责将B类提供给A类。它通常用于测试Spring将提供不同的B类(例如模拟)
当然,您可以自己完成所有这些工作,但如果让Spring(或任何其他DI框架)为您完成这些工作,通常会减少工作量。依赖项注入解决的主要问题是单元测试。假设您有一个依赖于NuclearPlant的开门服务。要对DoorOpeningService进行单元测试,您需要有一个NuclearPlant(仅用于测试打开的门,这非常昂贵且难以设置) 如果开门服务的代码如下:
public class DoorOpeningServiceImpl implements DoorOpeningService {
private NuclearPlant plant;
public DoorOpeningServiceImpl() {
this.plant = SomeNamingService.lookup("nuclearPlant");
}
public void openDoors() {
int electricity = plant.getSomeElectricity();
...
}
}
DoorOpeningService很难进行单元测试
依赖项注入允许将NuclearPlant提供给DoorOpeningService。因此,你不需要一个真正的核电站,你可以给它一个假的,它总是提供一些电力,而不需要所有真正的核电站基础设施。因此,开门服务更易于测试:
public class DoorOpeningServiceImpl implements DoorOpeningService {
private NuclearPlant plant;
// The plant is injected by constructor injection
public DoorOpeningServiceImpl(NuclearPlant plant) {
this.plant = plant;
}
public void openDoors() {
int electricity = plant.getSomeElectricity();
...
}
}
有一个框架为您注入依赖项会更容易,而且还允许添加其他方面(如果您愿意,可以添加拦截器)。例如,Spring可以为该实现注入一个代理,而不是您的NuclearPlant实现,该代理可以确保每次调用工厂时,事务都是打开的,或者调用方有权调用其方法,或者收集统计数据以帮助诊断应用程序中的慢部件。使用依赖项注入的好处在于您有如下代码
Interface i;
if (useA) {
i = new A();
} else if (useB) {
i = new B();
} else if (useC) {
i = new C();
}
i.call();
您有几种不同类型的接口
,您需要选择在运行程序时使用哪种接口,因为您不知道在编写程序时使用哪种接口。这意味着启动程序时需要以某种方式找到useA
、useB
和useC
。典型的方法是加载检测代码或属性文件,设置这些值
此外,对于主要由外部调用的代码组成的web应用程序,“谁来实际执行”部分可能很难确定
依赖项注入形式化如下:
@Injection Interface i;
i.call();
Spring使i
自动初始化,因此您不必在代码中以标准方式担心标志或工厂的位置。处理A、B、C与实际代码的这种分离已被证明可以创建非常干净的代码
编辑:重温这个问题时,我明白了问题的实质是“既然可以对getter和setter执行相同的操作,为什么还要使用依赖注入?” 在我看来,需要认识到的重要一点是,依赖注入不能比使用getter和setter做的更多,但是可以使用getter和setter的唯一地方是在创建新对象的代码中。在Java中,这是
new
语句。换句话说,代码需要知道所有的细节,而它通常不知道。这就是为什么我们有工厂工厂——作为一种使决策过程更接近运行时的手段——依赖注入本质上就是这样。工厂框架。但需要通知的关键是,它允许您将配置部分与工作部分分离,并将其放在其他地方
我不知道问题是什么,为什么Springs的解决方案将指定要在XML文件中使用的接口实现(或使用注释)比简单地用一行代码实例化正确的接口要好
首先,无论你的应用程序是否是web应用程序、桌面等,配置看起来都是一样的(并且可以在相同的位置找到)。这是一个小优势,但我发现在继承项目时它相当方便
第二,你经常需要某种配置的外部化,比如在不重建应用程序的情况下更改外部服务的URL、超时限制等,这意味着不管怎样,你最终都会得到一个配置文件。碰巧Spring的配置格式非常强大——除了能够硬编码之外(比如说“beanfooDao
是使用这个数据库的JpaFooDao
的一个实例”),您还可以使用系统属性(使用${propertyName}
语法),例如可以,等等。所有这些你都可以自己做,但不是没有大量的工作
我和任何人一样讨厌XML