Spring IoC 与 依赖注入(DI)

前言:

在前面的学习里,我们了解了 Spring Boot 和 Spring MVC ,可以完成一些简单功能的开发了,但是什么是Spring呢? 它们三者之间又有什么关系?咱们带着问题去学习,我们先看看什么是 Spring.

一,Spring 是什么?

通过前面的学习,我们知道了Spring是一个功能强大、灵活易用的Java框架,它提供了许多用于构建现代企业应用程序的工具和技术。但是这个概念相对来说,还是有些抽象.
我们可以通过一句话来概括Spring,那就是:Spring 是包含了众多工具方法的 IoC 容器. 那什么是容器? 什么是IoC容器?

二,什么是容器?

容器是用来容纳某种物体的装置,生活中的水杯,冰箱,水壶等等这些都是容器.在我们之前学习中接触的容器有哪些?

  • List/ Map — 数据存储的容器
  • Tomcat — Web 容器

三,什么是 IoC?

1️⃣ IoC 是 Spring 的核心思想,那什么是IoC 呢?

其实在前面我们已经使用过了,我们在前面类上添加的 @RestController@Controller 注解,就是把这个对象交给Spring 管理,Spring 框架启动时就会加载该类.它将对象交给Spring框架来管理。
简单来说,就是由Spring框架来负责对象的创建和管理,这就是IoC思想.
IoC(控制反转): Spring 是一个 “控制反转” 的容器 .

2️⃣ 什么是控制反转呢?

就是 控制权 反转,什么控制权发生了反转呢,是获得依赖对象的过程被反转了,也就是说,当需要某个对象时,不需要在通过 new 创建对象了,把创建对象的任务交给容器,程序中只需要 依赖注入(DI) 就可以了,这个容器称为: IoC 容器.
Spring 是一个 IoC 容器,所以有时 Spring 也称为 Spring 容器.

四,介绍 IoC

接下来我们通过案例来了解一下什么是IoC.
在这里插入图片描述

接下来需求有了变更: 随着对车的需求量越来越大,个性化需求也越来越多,我们需要加工多种尺寸的轮胎,这时候就要对程序就行修改了,修改后的代码如下图所示:
在这里插入图片描述

修改之后,其他调用程序也会报错,我们需要继续修改
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从以上代码可以看出,以上程序的问题是: 当底层代码改动之后,整个调用链上的所有代码都需要修改.程序的耦合性非常高(修改一处代码,影响其它处的代码修改).

我们可以尝试换一种思路,我们先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘来设计轮子.这时候,依赖关系就倒置过来了: 轮子依赖底盘,底盘依赖车身,车身依赖汽车.

如何实现呢?

我们可以尝试不在每个类中自己创建下级类,如果自己创建下级类就会出现当下级类发生改变操作,自己也要跟着修改.此时,我们只需要将原来由自己创建的下级类,改为 传递 的方式(也就是注入的方式).
因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦.

具体代码实现如下:

public class IocCar {
   
    public static void main(String[] args) {
   
        Tire tire = new Tire(17);
        Bottom bottom = new Bottom(tire);
        Framework framework = new Framework(bottom);
        Car car = new Car(framework);

        car.run();
    }


static class Car {
   
    private Framework framework;

    public Car(Framework framework) {
   
        this.framework = framework;

        System.out.println("car init...");
    }

    public void run() {
   
        System.out.println("car run...");
    }
}

static class Framework {
   
    private Bottom bottom;

    public Framework(Bottom bottom) {
   
        this.bottom = bottom;

        System.out.println("Framework init...");
    }
}

static class Bottom {
   
    private Tire tire;

    public Bottom(Tire tire) {
   
        this.tire = tire;

        System.out.println("bottom init...");
    }
}

static class Tire {
   
    private int size;

    public Tire(int size) {
   
        this.size = size;

        System.out.println("tire init...size: " + size );
        }
    }
}

代码经过以上调整,无论底层类如何变化,整个调用链不用做任何改变的,这样就完成代码之间的解耦.

五,IoC 优势

传统开发与IoC开发的对比:

在这里插入图片描述

从中我们发现一个规律,通用程序的实现代码,类创建属性是反的,传统代码是Car 控制并创建了 Framework, Framework 控制并创建了 Bottom,依次往下,而 改进之后的控制权发生的反转 ,不再是使用方创建对象并依赖对象了,而是把依赖注入当前对象中,依赖对象的控制权不再由当前类控制了 .

这样的话,即使依赖类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想.学到这里,我们大概知道什么是控制反转了,那什么是控制反转容器呢,也就是 IoC 容器.

从上面也可以看出来,IoC容器具备以下优点:

  1. 资源集中管理: IoC容器会帮我们管理一些资源(对象等),我们使用时,只需要去取就可以了.
  2. 我们在创建实例的时候不需要了解其中的细节,降低使用资源双方的依赖程度(耦合性).

Spring 就是一种IoC容器,帮助我们来做这些资源管理.

六,DI 介绍

在IoC开发中,需要把依赖注入当前对象中,那么 依赖注入 又是什么呢?

DI: Dependency Injection(依赖注⼊)
容器在运⾏期间, 动态的为应⽤程序提供运⾏时所依赖的资源,称之为依赖注⼊。

程序运⾏时需要某个资源,此时容器就为其提供这个资源.
从这点来看, 依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。

上述代码中, 是通过构造函数的⽅式, 把依赖对象注⼊到需要使⽤的对象中的
在这里插入图片描述

IoC是一种思想,也是"目标",而思想只是一种指导原则,最终还是要有可行的落地方案,而 DI 就属于具体的实现. 也可以说,DI 是 IoC 的一种实现.

七,IoC & DI

对 IoC 和 DI 有了初步的了解,我们接下来具体学习Spring IoC 和 DI 的代码实现

Spring 是一个 IoC 容器 ,作为容器,就应该有两个基本功能:

Spring 容器 管理的主要是对象,这些对象,我们称之为 “Bean”.我们把这些对象交由Spring管理,由Spring来父子对象的创建和销毁.我们程序只需要告诉Spring,那些需要存,以及如何从Spring中取对象.

首先,让我们看一个使用 Java 配置实现DI的例子:

  • 创建一个接口
public interface MessageService {
     
    String getMessage();  
}
  • 创建两个不同的实现:
@Component  
public class MessageServiceOne implements MessageService {
     
    @Override  
    public String getMessage() {
     
        return "Hello from MessageServiceOne";  
    }  
}  
  
@Component  
public class MessageServiceTwo implements MessageService {
     
    @Override  
    public String getMessage() {
     
        return "Hello from MessageServiceTwo";  
    }  
}
  • 创建一个使用MessageService的类:
@Component  
public class MessagePrinter {
     
    private final MessageService messageService;  
  
    @Autowired  
    public MessagePrinter(MessageService messageService) {
     
        this.messageService = messageService;  
    }  
  
    public void printMessage() {
     
        System.out.println(messageService.getMessage());  
    }  
}

在上面的示例中,我们使用Java配置来定义bean,

  1. 将实现类交给Spring管理,使用注解: @Component
  2. 注解运行时依赖的对象使用注解: @Autowired

Spring的IoC和DI的基本实现, 提高了代码的可维护性和可扩展性。通过使用Spring的IoC和DI功能,我们可以更专注于业务逻辑的实现,而不需要过多关注对象的创建和依赖管理。

八,IoC 详解

通过上面的示例,我们已经知道了 Spring IoC 和 DI 的基本操作,接下来我们系统的学习 Spring IoC 和 DI 的操作吧.

前面我们提到 IoC 控制反转,就是将对象的控制权交给Spring的IoC容器,由IoC容器创建及管理对象,也就是Bean 的存储.

🔸Bean 的存储

在之前的示例里,要把某个对象交给 IoC 容器管理时, 需要在类上添加一个注解: @Component 而Spring为了更好的服务web应用,提供了更丰富的注解.

共有两类注解类型可以实现:

  1. 类注解:@Controller,@Service,@Repository,@Component,@Configuration。
  2. 方法注解:@Bean。

1️⃣@Controller(控制器存储)

使用 @Controller 存储 Bean代码如下:

@Controller //将对象存储到 Spring 中
public class UserController {
   
    public void sayHi() {
   
        System.<
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值