【Spring】什么是Spring?

什么是Spring?

Spring是一个开源的轻量级框架 ,是为了简化企业级开发而设计的。我们通常讲的Spring一般指的是Spring Framework。Spring的核心是控制反转 (IoC -Inversion of Control)和面向切面编程 (AOP-Aspect-Oriented Programming)。这些功能使得开发者可以专注于业务逻辑的实现,不用去关注底层的实现。除此之外,Spring还可以与第三方库和框架集成,如Mybatis等,使得我们开发更加方便。

我们来看看官方的解释:

Spring | Why Spring

可以看到,spring包含了很多模块,简单来说:Spring是包含了很多工具方法的IoC容器

什么是容器?

Spring容器是Spring框架中的核心组成部分,负责管理Spring Bean的生命周期和依赖关系,Spring容器是一个BeanFactory(Bean工厂),负责实例化、配置和管理Bean。

在Spring程序中,我们所有的Bean都是存放在容器中,通过IoC(控制反转)技术进行管理。Spring容器通过自动装配(autowiring)的方式将各个Bean之间建立联系,从而减少手动配置的工作量。同时,Spring容器还提供了丰富的扩展机制,使得开发者可以根据自己的需求对bean进行定制化配置。

什么是IoC?

Spring IoC(控制反转),是一种设计思想 ,通过将对象的创建和管理权交给了Spring容器降低了程序之间的耦合性,

在Spring框架中,IoC主要通过XML配置文件、注解或Java配置等方式实现。通过使用IoC,应用程序的各个模块之间就可以以低耦合的形式进行协同工作,提高应用程序的可扩展性和可维护性。

传统程序开发流程

我们来举个例子,来更好的理解上面所述内容。

假设我们现在要生产一辆车,其基本思路如下:

按照传统的做法,我们生产一辆车,车的构成需要依赖车身(Framework),而车身需要依赖底盘(Bottom),底盘需要依赖轮胎(Tire)。

按照这种思路,我们用代码实现如下:

java 复制代码
public class CarProduct {
    public static void main(String[] args) {
        Car car = new Car();
        car.init();
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;

        public Car() {
            framework = new Framework();
        }

        public void init() {
            framework.init();
        }
    }

    /**
     * 车身Framework
     */
    static class Framework {

        private Bottom bottom;

        public Framework() {
            bottom = new Bottom();
        }

        public void init() {
            bottom.init();
        }
    }

    /**
     * 底盘Bottom
     */
    static class Bottom {

        private Tire tire;

        public Bottom() {
            tire = new Tire();
        }

        public void init() {
            tire.init();
        }
    }

    /**
     * 轮胎Tire
     */
    static class Tire {
        private int size = 20;//轮胎大小

        public void init() {
            System.out.println("轮胎大小:" + size);
        }
    }
}

我们可以看到,在上面的代码中,轮胎的尺寸是固定的,但是现在车的数量非常多,车轮胎的尺寸不可能都是一样的,所以我们就需要生产出各种尺寸大小的轮胎。我们需要对上面的代码进行修改:

java 复制代码
public class CarProduct {
    public static void main(String[] args) {
        Car car = new Car();
        car.init(10);
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;

        public Car() {
            framework = new Framework();
        }

        public void init(int size) {
            framework.init(size);
        }
    }

    /**
     * 车身Framework
     */
    static class Framework {

        private Bottom bottom;

        public Framework() {
            bottom = new Bottom();
        }

        public void init(int size) {
            bottom.init(size);
        }
    }

    /**
     * 底盘Bottom
     */
    static class Bottom {

        private Tire tire;

        public Bottom() {
            tire = new Tire();
        }

        public void init(int size) {
            tire.init(size);
        }
    }

    /**
     * 轮胎Tire
     */
    static class Tire {

        public void init(int size) {
            System.out.println("轮胎大小:" + size);
        }
    }
}

我们可以看到,虽然满足我们的需求了,但是在上面的代码中,不难看到,当最底层的代码修改后,整个调用链上的代码都需要进行修改,这样耦合度就非常高了。

那么如果解决上面出现的这种问题呢?

在上面的代码中,我们都是在每个类中创建下一个要调用的类,这样的耦合度就非常高。

那么我们可以不在类中创建下级类,而是改为传递的方式(即注入),这样我们就能实现解耦,下级类的改变发生变化,对于当前类来说,也无需修改任何代码。

解耦指的是:解决了代码之间的依赖程度,也可以叫做程序相关性,好的程序的代码的耦合性是很低的,也就是代码之间要解耦

这就好比我们生产一辆汽车,如果所有的配件都是自己制造的,那么当客户要改变需求时,如,客户想要一个比较大的轮胎,那么我们就需要自己生产,这样的效率是非常低的,但如果我们把轮胎的生产外包出去,那么就算轮胎的尺寸要发生改变,我们也能向代理公厂下单即可,无需自己生产,这样效率就提高了不少。

控制反转程序开发流程(IoC)

根据上面所述,对代码进行修改:

java 复制代码
**
 * CarProduct类是汽车生产模型的示例,展示了如何通过组合不同类来构建复杂的对象结构
 */
public class CarProduct {
    /**
     * 程序的入口点
     * 创建汽车对象及其组成部分,并初始化
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 创建轮胎对象,指定轮胎大小
        Tire tire = new Tire(20);
        // 创建底盘对象,包含上面创建的轮胎
        Bottom bottom = new Bottom(tire);
        // 创建车身对象,包含上面创建的底盘
        Framework framework = new Framework(bottom);
        // 创建汽车对象,包含上面创建的车身
        Car car = new Car(framework);
        // 初始化汽车对象
        car.init();
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;

        /**
         * 构造方法,初始化汽车的车身
         * @param framework 汽车的车身
         */
        public Car(Framework framework) {
            this.framework = framework;
        }

        /**
         * 初始化汽车对象,包括其车身
         */
        public void init() {
            framework.init();
        }
    }

    /**
     * 车身Framework
     */
    static class Framework {

        private Bottom bottom;

        /**
         * 构造方法,初始化车身的底盘
         * @param bottom 车身的底盘
         */
        public Framework(Bottom bottom) {
            this.bottom = bottom;
        }

        /**
         * 初始化车身对象,包括其底盘
         */
        public void init() {
            bottom.init();
        }
    }

    /**
     * 底盘Bottom
     */
    static class Bottom {

        private Tire tire;

        /**
         * 构造方法,初始化底盘的轮胎
         * @param tire 底盘的轮胎
         */
        public Bottom(Tire tire) {
            this.tire = tire;
        }

        /**
         * 初始化底盘对象,包括其轮胎
         */
        public void init() {
            tire.init();
        }
    }

    /**
     * 轮胎Tire
     */
    static class Tire {

        private int size;//轮胎大小

        /**
         * 构造方法,初始化轮胎的大小
         * @param size 轮胎的大小
         */
        public Tire(int size) {
            this.size = size;
        }

        /**
         * 初始化轮胎对象,打印轮胎大小
         */
        public void init() {
            System.out.println("轮胎大小:" + size);
        }
    }
}

我们可以看到,通过上面的修改,就算底层类发生变化,整个调用链的代码也是不用做任何修改的,这样就实现代码之间的解耦,从而提高了代码的灵活性、复用性。

我们来对比一下传统程序开发流程和控制反转程序开发流程:

我们可以看到,传统的开发流程是:Car依赖Framework,Framework依赖Bottom,.. .。而在改进之后的代码中,控制权发生了反转,不再是由上级对象创建下级对象并控制下级对象,而是下级对象注入到上级对象中,下级对象不再受上级对象的控制,这样就算下级对象发生改变,也不会影响到上级对象,这就是典型的控制反转,也就是IoC的实现思想

如何理解Spring IoC

在以往的程序设计中,对象之间的依赖关系通常是由程序内部通过new关键字来实现的,这样的方式,会导致程序内部与具体实现的对象紧密联系(即耦合度高),一旦对象的实现发生改变,那么对于程序中的一部分代码也需要进行修改,这不仅增加了开发成本,而且也增加了代码的维护难度。

Spring IoC则是将对象的创建和管理权交给了Spring容器 。在Spring容器中,所有的对象称为Bean ,并通过配置文件或注解等方式来进行获取对象。当程序某处需要用到Bean对象时,Spring容器就会负责查找、创建、注入Bean对象。而程序本身不需要关心Bean对象时如何实例化和管理的。这种方式的创建和管理权从原先的程序中转移到Spring容器中,从而实现了控制反转(IoC)。

Spring IoC的优点

  • 降低耦合度:通过把对象的实例和管理权交给Spring容器,从而让程序与对象之间的耦合性降低,使得代码更加灵活、可维护、可复用。
  • 提高可扩展性:由于对象的创建和管理权交给了Spring容器,当我们需要添加新的功能或模块时,我们只需要在Spring中注册相应的bean即可。
  • 简化开发:使用Spring IoC可以简化开发。开发者只需要关注业务逻辑的实现,而不需要花费过多的精力在对象的创建和管理上。
  • 提高性能:虽然使用Spring IoC会增加一些额外的开销,但在大多数情况下,这种开销是微不足道的。而且,通过使用Spring IoC,可以减少不必要的对象创建和销毁,从而提高应用程序的性能。

DI(依赖注入)

DI(Dependcy Injection,即依赖注入)是一种软件设计模式,用于实现松耦合和可测试性的代码结构。在寻常的编程中,对象通常自己负责创建和管理它锁依赖的其他对象,这样导致了对象之间的耦合度高,使得对象难以复用和测试。

DI是一种实现控制反转(Inversion of Control,简称 IoC)的机制 。它允许对象之间的依赖关系由外部容器(Spring 容器)来管理,而不是由对象自身来创建或查找依赖对象 。这种方式可以减少对象之间的耦合性,提高代码的可重用性和可维护性

DI的实现方式

DI的主要实现 方式包括构造函数注入、属性注入和方法注入

  • 构造函数注入是最常见的DI方式,它通过在对象的构造函数中传递依赖对象来实现。
  • 属性注入是通过设置对象的属性来注入依赖对象。
  • 方法注入是一种更灵活的DI方式,它通过在对象的方法中传递依赖对象来实现。

DI的优点

  • 降低耦合度DI使得对象之间的耦合度降低,因为对象不直接创建依赖,而是通过外部注入的方式获得。这使得每个对象更加独立,更易于管理和维护。
  • 提高代码的可维护性:由于对象之间的耦合度降低,修改一个对象时对其他对象的影响也会减少,这使得代码更易于维护和升级。
  • 提高灵活性:DI使得对象的依赖关系可以动态地管理和修改,这使得代码更加灵活,可以根据实际需求进行修改和扩展。
  • 增强代码的可测试性:依赖注入使得单元测试变得更加容易。开发者可以通过注入模拟(mock)对象或存根(stub)来测试组件的行为,而不需要依赖于实际的依赖对象。
  • 提高代码的可重用性:由于对象不依赖于具体的实现,而是依赖于抽象(接口或抽象类),因此可以更容易地替换对象的实现,从而提高代码的可重用性。

Spring相关网站

Spring官方网站:Spring | Homehttps://spring.io/https://spring.io/

Spring Framework官方文档:Spring Framework 文档 :: Spring Frameworkhttps://docs.spring.io/spring-framework/reference/https://docs.spring.io/spring-framework/reference/

Spring Boot官方文档:Spring Boot :: Spring Boothttps://docs.spring.io/spring-boot/index.htmlhttps://docs.spring.io/spring-boot/index.html

Spring Cloud官方文档:Spring Cloudhttps://spring.io/projects/spring-cloud#learnhttps://spring.io/projects/spring-cloud#learn

Spring源代码仓库:Spring · GitHubhttps://github.com/spring-projectshttps://github.com/spring-projects

Spring源代码仓库中文文档:Spring Framework 中文文档https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/

Spring Boot中文文档:Spring Boot 参考https://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-startedhttps://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-started

Spring Cloud中文文档:Spring Cloud 中文文档https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/


以上就是本篇所有内容啦~

若有不足,欢迎指正~

相关推荐
计算机毕业设计小帅7 分钟前
【2026计算机毕业设计】基于Springboot的校园电动车短租平台
spring boot·后端·课程设计
调试人生的显微镜7 分钟前
Web前端开发工具实战指南 从开发到调试的完整提效方案
后端
静心观复7 分钟前
drawio画java的uml的类图时,class和interface的区别是什么
java·uml·draw.io
Java水解8 分钟前
【SQL】MySQL中空值处理COALESCE函数
后端·mysql
Laplaces Demon9 分钟前
Spring 源码学习(十四)—— HandlerMethodArgumentResolver
java·开发语言·学习
guygg8813 分钟前
Java 无锁方式实现高性能线程
java·开发语言
ss27314 分钟前
手写Spring第7弹:Spring IoC容器深度解析:XML配置的完整指南
java·前端·数据库
Python私教16 分钟前
DRF:Django REST Framework框架介绍
后端·python·django
间彧18 分钟前
Java HashMap如何合理指定初始容量
后端
用户40993225021231 分钟前
PostgreSQL全表扫描慢到崩溃?建索引+改查询+更统计信息三招能破?
后端·ai编程·trae