Spring IoC&DI(1)—入门

简介: Spring IoC&DI(1)—入门

       通过前面的学习,我们知道Spring是一个开源框架,它能让我们的开发更简单,它支持广泛的应用场景,有着活跃而庞大的社区,这也是Spring长久不衰的原因。但是这个概念还是比较抽象的,我们用一句更具体的话来概括Spring:Spring是包含了众多工具方法的IoC容器


一、IoC & DI入门


1、Spring是什么

(1)什么是容器?

       容器是用来容纳某种物品的(基本)装置。——来自:百度百科。生活中的水杯、垃圾桶、冰箱等等这些都是容器,之前接触过的容器:List/Map->数据存储容器、Tomcat->Web容器。

(2)什么是IoC?

       IoC是Spring的核心思想,也是常见的面试题,那么什么是IoC呢?其实IoC在前面的代码练习已经使用过了,比如在类上面添加 @RestController 和 @Controller 注解,就是把这个对象交给Spring管理,Spring框架启动时,就会加载该类。——把对象交给Spring管理,这就是IoC思想

      IoCInversion of Control(控制反转),也就是说Spring是一个“控制反转”的容器

什么是控制反转呢?就是控制权反转。什么控制权发生了反转?获得依赖对象的过程被反转了也就是说,当需要某个对象时,传统开发模式需要自己通过 new 创建对象,现在不需要再进行创建了,把创建对象的任务交给容器,程序中只需要依赖注入(Dependency Injection,简称DI)就可以了。这个容器称为:IoC容器。Spring是一个IoC容器,所以有时也称为Spring容器

      控制反转是一种思想,在生活中也处处体现比如自动驾驶,传统驾驶方式,车辆的横向和纵向驾驶控制权由驾驶员来控制,现在交给了驾驶自动化系统来控制,这也是控制反转思想在生活中的实现;还有招聘,企业的员工招聘、入职、解雇等控制权,由老板转交给HR(人力资源)来处理;还有外包等等


二、IoC介绍


下面通过案例来介绍什么是IoC,现在需求:造一辆车

1、传统程序开发

       我们是实现思路是这样的:先设计轮子(Tire),然后根据轮子的大小设计底盘(;),接着根据底盘设计车身(FrameWork),最后根据车身设计好整个汽车(Car)。这里就出现了一个 “依赖” 关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子。如图:

       代码实现如下:

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.run();
    }
}
 
public class Car {
    private FrameWork frameWork;
    public Car() {
        frameWork = new FrameWork(17);
        System.out.println("frameWork init....");
    }
    public void run() {
        System.out.println("Car run...");
    }
}
 
public class FrameWork {
    private Bottom bottom;
    public FrameWork(int size) {
        bottom = new Bottom(size);
        System.out.println("Bottom init...");
    }
}
 
 
public class Bottom {
    private Tire tire;
    public Bottom(int size) {
        tire = new Tire(size);
        System.out.println("Tire init....");
    }
}
 
public class Tire {
    private int size;
    public Tire(int size) {
        this.size = size;
    }
}

       程序跑起来,控制台结果如图:

       

       但是现在又有需求了,要修改轮胎的颜色,那就要多添加一个属性,那么传参的时候,Car类、FrameWork类、Bottom类、Tire类的构造函数都要多添加一个元素,传参也要多传一个颜色属性。那么这样的话,耦合就很高而这也只是简单的给轮胎添加一个属性,随着项目需求的增加,项目也会越来越复杂,现在的代码可维护性也很差,就不太合适了。所以,要进行改进

2、解决方案

       上面的程序中,我们是根据轮胎的尺寸设计底盘的,轮胎的尺寸已改,底盘的设计也就得改,而车身依赖底盘,就会导致一连串的问题,几乎整个设计都得改。

       现在尝试换一种思路,我们先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘设计轮胎。这时候,依赖关系就反转过来了:轮胎依赖底盘,底盘依赖车身,车身依赖汽车

这就类似我们造一辆完整的汽车,如果所有的配件都是自己造,那么客户需求发生改变的时候,比如轮胎尺寸不再是原来的尺寸了,那我们就要自己手动来改了,但如果把轮胎外包出去,那么即使轮胎的尺寸发生改变,那么我们只需要向代理工厂下订单就行了,我们自身是不需要出力的

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

3、IoC程序开发

       基于以上思路,我们把调用汽车的程序示例改造一下,把创建子类的方式,改为注入传递的方式。具体代码如下:

public class Main {
    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();
    }
}
 
public class Car {
    private FrameWork frameWork;
    public Car(FrameWork frameWork) {
        this.frameWork = frameWork;
        System.out.println("frameWork init....");
    }
    public void run() {
        System.out.println("Car run...");
    }
}
 
public class FrameWork {
    private Bottom bottom;
    public FrameWork(Bottom bottom) {
        this.bottom = bottom;
        System.out.println("Bottom init...");
    }
}
 
public class Bottom {
    private Tire tire;
    public Bottom(Tire tire) {
        this.tire = tire;
        System.out.println("Tire init....");
    }
}
 
public class Tire {
    private int size;
    public Tire(int size) {
        this.size = size;
        System.out.println("size:" + size);
    }
}

       这样,如果轮胎需要修改尺寸,或者添加一个属性,只需要修改Tire类就好了,其他类不需要修改,达到了解耦的效果。

4、IoC优势

传统代码中的对象创建顺序是:Car -> Framework -> Bottom -> Tire

改进之后解耦的代码的对象创建顺序是:Tire -> Bottom -> Framework -> Car

       我们发现了一个规律,通过程序的实现代码,类的创建顺序是反的,传统代码是Car控制并创建了Framework,Framework的创建也会继续创建Bottom,依次往下递推而改进后的控制权发生了反转,不再是使用方创建对象并控制依赖对象了,而是把依赖对象注入到当前对象中,依赖对象的控制权不再由当前类控制。这样的话,即使依赖类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也是IoC的实现思想。

       而控制反转容器也就是IoC容器,如图:

       这部分代码,也是IoC容器做的工作。

       从上面可以看出,IoC具有以下优点:资源不由使用资源的双方管理,而由使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理第二,降低使用资源双方的依赖程度,也就是我们说的耦合度

       资源集中管理IoC容器会帮我们管理一些资源(对象等),我们需要使用时,只需要从IoC容器中去取就可以了

      解耦合我们在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,也就是耦合度

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


三、DI介绍


       DIDependency Injection(依赖注入)容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称为依赖注入

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

       上面改进后的代码,就是通过构造函数,把依赖对象注入到需要使用的对象中。如图:

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

       就像我今天心情比较好,想吃顿大餐奖励自己,那么 “吃大餐” 就是思想和目标(是IoC),但最后我是吃什么大餐,肯德基还是海底捞等等,这个就是具体实现,就是DI。

相关文章
|
8天前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
110 2
|
5月前
|
人工智能 Java API
Spring AI 实战|Spring AI入门之DeepSeek调用
本文介绍了Spring AI框架如何帮助Java开发者轻松集成和使用大模型API。文章从Spring AI的初探开始,探讨了其核心能力及应用场景,包括手动与自动发起请求、流式响应实现打字机效果,以及兼容不同AI服务(如DeepSeek、通义千问)的方法。同时,还详细讲解了如何在生产环境中添加监控以优化性能和成本管理。通过Spring AI,开发者可以简化大模型调用流程,降低复杂度,为企业智能应用开发提供强大支持。最后,文章展望了Spring AI在未来AI时代的重要作用,鼓励开发者积极拥抱这一技术变革。
1890 71
Spring AI 实战|Spring AI入门之DeepSeek调用
|
6月前
|
安全 Java 数据库
Spring Security 实战指南:从入门到精通
本文详细介绍了Spring Security在Java Web项目中的应用,涵盖登录、权限控制与安全防护等功能。通过Filter Chain过滤器链实现请求拦截与认证授权,核心组件包括AuthenticationProvider和UserDetailsService,负责用户信息加载与密码验证。文章还解析了项目结构,如SecurityConfig配置类、User实体类及自定义登录逻辑,并探讨了Method-Level Security、CSRF防护、Remember-Me等进阶功能。最后总结了Spring Security的核心机制与常见配置,帮助开发者构建健壮的安全系统。
362 0
|
3月前
|
前端开发 Java API
基于 Spring Boot 3 与 React 的 Java 学生信息管理系统从入门到精通实操指南
本项目基于Spring Boot 3与React 18构建学生信息管理系统,涵盖前后端开发、容器化部署及测试监控,提供完整实操指南与源码,助你掌握Java全栈开发技能。
170 0
|
4月前
|
Java 关系型数据库 MySQL
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
333 1
|
4月前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
470 0
|
5月前
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
|
7月前
|
Java 容器 Spring
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
6月前
|
存储 安全 Java
Spring Security 入门与详解
Spring Security 是 Spring 框架中的核心安全模块,提供认证、授权及防护功能。本文详解其核心概念,包括认证(Authentication)、授权(Authorization)和过滤器链(Security Filter Chain)。同时,通过代码示例介绍基本配置,如 PasswordEncoder、UserDetailsService 和自定义登录页面等。最后总结常见问题与解决方法,助你快速掌握 Spring Security 的使用与优化。
1432 0