总结Spring IOC和DI

Spring是包含了众多⼯具⽅法的IoC容器

目录

1 IOC

1.1 什么是容器

1.2 什么是IOC?

1.2.1 传统程序开发

1.2.2 问题分析 

1.2.3 解决⽅案

1.2.4 IoC程序开发

1.2.5 IoC优势

1.3 DI 介绍


1 IOC

1.1 什么是容器

容器是⽤来容纳某种物品的(基本)装置。⽣活中的⽔杯,垃圾桶,冰箱等等这些都是容器。

我们之前的数据存储容器, List/Map, web容器 Tomcat

1.2 什么是IOC?

其实我们在一开始学习框架的时候, 在类上⾯添加 @RestController 和 @Controller 注解,就是把这个对象交给Spring管理,Spring框架启动时就会加载该类.把对象交 给Spring管理,就是IoC思想.

IoC: Inversion of Control (控制反转),也就是说Spring是⼀个"控制反转"的容器.

什么是控制反转呢? 也就是控制权反转.什么的控制权发⽣了反转? 获得依赖对象的过程被反转了 也就是说,当需要某个对象时,传统开发模式中需要⾃⼰通过new创建对象,现在不需要再进⾏创 建, 把创建对象的任务交给容器, 程序中只需要依赖注⼊(DependencyInjection,DI)就可以了. 这个容器称为:IoC容器. Spring是⼀个IoC容器,所以有时Spring也称为Spring容器.

1.2.1 传统程序开发

假如我们现在要造一辆车, 我们的实现思路是这样的:

先设计轮⼦(Tire),然后根据轮⼦的⼤⼩设计底盘(Bottom),接着根据底盘设计⻋⾝(Framework),最 后根据⻋⾝设计好整个汽⻋(Car)。这⾥就出现了⼀个"依赖"关系:汽⻋依赖⻋⾝,⻋⾝依赖底盘,底盘依赖轮⼦.

public class NewCarExample {
    public static void main(String[] args) {
        Car car = new Car();
        car.run();
    }
    /**
     *
     汽⻋对象
     */
    static class Car {
        private Framework framework;
        public Car() {
            framework = new Framework();
            System.out.println("Car init....");
        }
        public void run(){
            System.out.println("Car run...");
        }
    }
    /**
     *
     ⻋⾝类
     */
    static class Framework {
        private Bottom bottom;
        public Framework() {
            bottom = new Bottom();
            System.out.println("Framework init...");
        }
    }
    /**
     *
     底盘类
     */
    static class Bottom {
        private Tire tire;
        public Bottom() {
            this.tire = new Tire();
            System.out.println("Bottom init...");
        }
    }
    /**
     *
     轮胎类
     */
    static class Tire {
        //尺⼨
        private int size;
        public Tire(){
            this.size = 17;
            System.out.println(" 轮胎尺⼨: " + size);
        }
    }
}

1.2.2 问题分析 

这样的设计看起来没问题,但是可维护性却很低.

接下来需求有了变更: 随着对的⻋的需求量越来越⼤,个性化需求也会越来越多,我们需要加⼯多种尺⼨的轮胎. 那这个时候就要对上⾯的程序进⾏修改了,

修改后的代码如下所⽰: 修改之后,其他调⽤程序也会报错,我们需要继续修改 

那么这样的话车身类和汽车类的代码都要修改. 这样的话, 程序的耦合度就会非常高.

1.2.3 解决⽅案

在上⾯的程序中,我们是根据轮⼦的尺⼨设计的底盘,轮⼦的尺⼨⼀改,底盘的设计就得修改.同样因 为我们是根据底盘设计的⻋⾝,那么⻋⾝也得改,同理汽⻋设计也得改,也就是整个设计⼏乎都得改.

我们尝试换⼀种思路,我们先设计汽⻋的⼤概样⼦,然后根据汽⻋的样⼦来设计⻋⾝,根据⻋⾝来设计 底盘,最后根据底盘来设计轮⼦.这时候,依赖关系就倒置过来了:轮⼦依赖底盘,底盘依赖⻋⾝, ⻋⾝依赖汽⻋.

这就类似我们打造⼀辆完整的汽⻋,如果所有的配件都是⾃⼰造,那么当客⼾需求发⽣改变的时候, ⽐如轮胎的尺⼨不再是原来的尺⼨了,那我们要⾃⼰动⼿来改了,但如果我们是把轮胎外包出去,那 么即使是轮胎的尺⼨发⽣变变了,我们只需要向代理⼯⼚下订单就⾏了,我们⾃⾝是不需要出⼒的.

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

1.2.4 IoC程序开发

基于以上思路,我们把调⽤汽⻋的程序⽰例改造⼀下,把创建⼦类的⽅式,改为注⼊传递的⽅式

public class NewCarExample {
    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.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 = 17;
            System.out.println(" 轮胎尺⼨: " + size);
        }
    }
}

代码经过以上调整,⽆论底层类如何变化,整个调⽤链是不⽤做任何改变的,这样就完成了代码之间 的解耦,从⽽实现了更加灵活、通⽤的程序设计了。

1.2.5 IoC优势

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

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

我们发现了⼀个规律,通⽤程序的实现代码,类的创建顺序是反的,传统代码是Car控制并创建了 Framework,Framework创建并创建了Bottom,依次往下,⽽改进之后的控制权发⽣的反转,不再 是使⽤⽅对象创建并控制依赖对象了,⽽是把依赖对象注⼊将当前对象中,依赖对象的控制权不再由 当前类控制了. 这样的话,即使依赖类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是IoC的 实现思想。

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

资源不由使⽤资源的双⽅管理,⽽由不使⽤资源的第三⽅管理,这可以带来很多好处。第⼀,资源集中管理,实现资源的可配置和易管理。第⼆,降低了使⽤资源双⽅的依赖程度,也就是我们说的耦合 度。 1. 资源集中管理: IoC容器会帮我们管理⼀些资源(对象等),我们需要使⽤时,只需要从IoC容器中去取 就可以了 2. 我们在创建实例的时候不需要了解其中的细节,降低了使⽤资源双⽅的依赖程度,也就是耦合度.

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

1.3 DI 介绍

DI: DependencyInjection(依赖注⼊)

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

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

上述代码中,是通过构造函数的⽅式,把依赖对象注⼊到需要使⽤的对象中.

IoC 是⼀种思想,也是"⽬标",⽽思想只是⼀种指导原则,最终还是要有可⾏的落地⽅案,⽽DI就属于 具体的实现。所以也可以说,DI是IoC的⼀种实现. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早点睡觉1.0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值