概念
虽然标题是Java基础知识,但依赖注入这个词是一个技术术语,不仅存在于Java中,也存在于软件工程领域。
在软件工程中,依赖注入(DI)是一种软件设计模式,也是一种实现控制反转(IoC)的技术。这种模式允许对象接收它们所依赖的其他对象。依赖关系是指接收者需要的对象。注入是指将依赖项传递给接收者的过程。注入后,接收者可以调用依赖项。
更详细地说:
依赖关系:一个类使用另一个类的实例来完成特定的任务。这称为依赖性。例如,类A依赖类B来完成某种功能,类B是类A的依赖。注入:将依赖项传递给使用它们的对象的过程。依赖注入可以通过构造函数、属性(setter)或接口来实现。
那么,这种设计模式有什么好处呢?主要有以下三点:
提高代码可维护性:将依赖项的创建和管理工作转移到外部容器,使您的代码更干净、更易于理解且更易于维护。提高代码可测试性:将依赖项注入代码中可以更轻松地编写测试用例来测试代码的不同部分。改善代码的松散耦合:代码不再需要与其依赖项的特定实现紧密耦合,从而更容易重构和扩展。
没有依赖注入的传统编程方式
让我们看一个例子。如果一个人想玩电脑游戏,他或她必须依赖电脑。这意味着person 类必须依赖于Computer 类。
没有依赖注入的传统编程需要接收者(人)自己创建依赖对象计算机。
计算机类{
公共无效玩(字符串游戏名称){
System.out.println(\’正在玩\’+游戏名称);
}
}
类人{
私人最终计算机计算机=新计算机();
公共无效playComputerGame(字符串whatGame){
computer.play(哪个游戏);
}
}
公共类主要{
公共静态无效主(字符串[] args){
人人=新人();
Person.playComputerGame(\’赛博朋克2077\’);
}
}
虽然这看起来工作正常,但是这种编写方式引入了一系列问题,包括代码可维护性、可测试性降低、松散耦合,甚至增加了代码复杂性。例如,如果您需要更改依赖项的实现,则该依赖项会硬编码在您的代码中,并且您必须手动更改使用该依赖项的所有代码。
让我们将上面的例子转化为现实生活。如果一个人想要使用电脑,他可以去网吧使用电脑,也可以去他的办公室使用公司的电脑。这个人依赖于计算机,但不是随身携带台式计算机并将其移动到任何地方,而是由外部来源提供计算机。
如果不需要依赖注入,则该人将随身携带计算机,但在依赖注入的情况下,该人将在网吧或工作场所使用计算机,但该人不需要将计算机交给他人使用它有。
让我们看看如何使用依赖注入重写这个示例。
依赖注入的方式
使用依赖注入时,依赖对象不与接收对象位于同一位置,而是以某种方式注入接收者。这就是依赖注入的常见实现方式。
构造函数注入:依赖项通过构造函数注入到类中。方法注入:通过方法将依赖注入到类中,并传递函数的参数。属性注入:通过属性、设置方法将依赖项注入到类中。接口注入:使用接口定义依赖项并将实现该接口的类注入到代码中。
接下来,重写上面的代码以使用这四种依赖项注入方法中的每一种。
构造函数注入
类人{
私人最终计算机。
public Person(Computercomputer) { //通过构造函数注入依赖computer
this.computer=计算机;
}
公共无效playComputerGame(字符串whatGame){
computer.play(哪个游戏);
}
}
公共类主要{
公共静态无效主(字符串[] args){
计算机计算机=新计算机();
人person=新人(计算机);
Person.playComputerGame(\’赛博朋克2077\’);
}
}
方法注入
类人{
公共无效playComputerGame(计算机计算机,字符串whatGame){
computer.play(哪个游戏);
}
}
公共类主要{
公共静态无效主(字符串[] args){
计算机计算机=新计算机();
人人=新人();
Person.playComputerGame(计算机, \’赛博朋克2077\’);
}
}
属性注入
类人{
个人电脑计算机。
public setComputer(Computercomputer) { //通过这个set方法注入依赖
this.computer=计算机;
}
公共无效playComputerGame(字符串whatGame){
computer.play(哪个游戏);
}
}
公共静态无效主(字符串[] args){
计算机计算机=新计算机();
人人=新人();
person.setComputer(计算机);
person.playComputerGame(\’赛博朋克2077\’);
}
接口注入
尽管接口注入在实际应用中很少见,但它对于某些场景来说是灵活的,特别是当类必须实现接口并且依赖项也必须通过接口方法通过注入对象传递时。
这种注入方法需要更多解释。在这种方法中,依赖项是通过接口方法注入到目标类中的,因此关键点是接收注入的目标类必须实现一个包含注入依赖项的方法的特定接口。
在上面的例子中,我们不能直接使用Person类,而是需要为其开发一个接口。
//定义玩家界面
界面玩家{
公共setComputer(computercomputer);
公共无效playComputerGame(字符串whatGame);
}
类Person 实现Gamer {
个人电脑计算机。
公共setComputer(计算机计算机){
this.computer=计算机;
}
公共无效playComputerGame(字符串whatGame){
computer.play(哪个游戏);
}
}
接口计算机{
公共无效玩(字符串游戏名称);
}
WindowsComputer 类实现Computer {
公共无效玩(字符串游戏名称){
System.out.println(\’在Windows电脑上玩\’ + 游戏名称);
}
}
LinuxComputer 类实现Computer {
公共无效玩(字符串游戏名称){
System.out.println(\’Linux电脑正在玩\’ + 游戏名称);
}
}
公共类主要{
公共静态无效主(字符串[] args){
玩家玩家=新人();
计算机windowsComputer=new WindowsComputer();
玩家.setComputer(windowsComputer);
gamer.playComputerGame(\’赛博朋克2077\’);
计算机linuxComputer=new LinuxComputer();
gamer.setComputer(linuxComputer);
gamer.playComputerGame(\’赛博朋克2077\’);
}
}
使用框架进行依赖注入
以上是依赖注入的传统实现,但在实际应用中,依赖注入通常是通过依赖注入框架来实现的。这些框架通过自动管理对象创建和依赖关系来简化开发。常见的依赖注入框架包括:
Spring (Java):一种流行的依赖注入和应用程序框架。 Google Guice (Java):一个轻量级依赖注入框架。 Dagger (Java/Android):适用于Android 和Java 的依赖注入框架。
#Java基础知识以上依赖注入相关资料仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/93259.html