问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

【Spring IoC】容器和IoC介绍以及IoC程序开发的优势

创作时间:
作者:
@小白创作中心

【Spring IoC】容器和IoC介绍以及IoC程序开发的优势

引用
CSDN
1.
https://blog.csdn.net/m0_74825614/article/details/145659373

Spring框架是Java开发中非常重要的技术,其核心概念之一就是IoC(控制反转)。本文将通过对比传统开发方式和IoC开发方式,深入浅出地解释IoC的概念,并通过汽车制造的例子帮助读者理解IoC的优势。

Spring 是什么

通过前面的学习,我们知道了Spring是一个开源框架,它让我们的开发更加简单。它支持广泛的应用场景,有着活跃而庞大的社区,这也是Spring能够长久不衰的原因。

但是这个概念相对来说是比较抽象的。我们用一句更具体的话来概括:Spring是包含了众多工具方法的IoC容器

  • 那问题来了,什么是容器?什么是IoC容器?

什么是容器

容器是用来容纳某种物品的(基本)装置。生活中的水杯、垃圾桶、冰箱等等这些都是容器。

我们想象,之前的内容中我们接触到了哪些容器:

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

什么是 IoC

IoC是Spring的核心思想,也是常见的面试题。其实我们在前面已经使用过了IoC,在类上面添加@RestController注解,就是把这个对象交给Spring管理,Spring框架启动时就会加载该类。把对象交给Spring管理,就是IoC思想

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

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

控制反转是一种思想,在生活中也是处处体现:

  • 自动驾驶:传统驾驶方式,车辆的横向和纵向驾驶控制权由驾驶员来控制,现在交给了驾驶自动化系统来控制,可也是控制反转思想在生活动的实现
  • 招聘:企业的员工招聘、入职、解雇等控制权,由老板转交给HR来处理

IoC 介绍

需求:造一台车

传统程序开发

我们的实现思路是这样的:先设计轮子(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("framework init...");  
        } 
        public void run() {  
            System.out.println("car run...");  
        }  
    }
    /**
     * 车身类
     */
     static class Framework {  
        private Bottom bottom;  
        
        public Framework() {  
            bottom = new Bottom();  
            System.out.println("bottom init...");  
        }  
    }   
    /**
     * 底盘类
     */
     static class Bottom {  
        private Tire tire;  
      
        public Bottom() {  
            tire = new Tire();  
            System.out.println("tire init...");  
        }  
    }
    /**
     * 轮胎类
     */
     public class Tire {  
        private int size = 21;  
      
        public Tire() {  
            System.out.println("tire size:" +size);  
        }  
    }
}

这样的设计看起来没问题,但是可维护性却很低。接下来需求有了变更:随着对的需求量越来越,个性化需求也会越来越多,我们需要加多种尺的轮胎。

那这个时候就要对上的程序进修改了,修改后的代码如下所:

修改之后,其他调程序也会报错,我们需要继续修改

完整代码如下:

public class NewCarExample {
    public static void main(String[] args) {
![](https://wy-static.wenxiaobai.com/chat-rag-image/16688192770303289929)
        Car car = new Car(21);
        car.run();    
    }
    
    /**
     * 汽车对象
     */
    static class Car {  
        private Framework framework;  
        
        public Car(int size) {  
            framework = new Framework(size);  
            System.out.println("framework init...");  
        } 
        public void run() {  
            System.out.println("car run...");  
        }  
    }
    /**
     * 车身类
     */
     static class Framework {  
        private Bottom bottom;  
        
        public Framework(int size) {  
            bottom = new Bottom(size);  
            System.out.println("bottom init...");  
        }  
    }   
    /**
     * 底盘类
     */
     static class Bottom {  
        private Tire tire;  
      
        public Bottom(int size) {  
            tire = new Tire(size);  
            System.out.println("tire init...");  
        }  
    }
    /**
     * 轮胎类
     */
     public class Tire {  
        private int size = 21;  
      
        public Tire(int size) {  
            this.size = size;
            System.out.println("tire size:" +size);  
        }  
    }
}

从以上代码可以看出,以上程序的问题是:当最底层代码改动之后,整个调链上的所有代码都需要修改

程序的耦合度常(修改处代码, 影响其他处的代码修改)

解决方法

在上的程序中, 我们是根据轮的尺设计的底盘,轮的尺改,底盘的设计就得修改. 同样因
为我们是根据底盘设计的,那么也得改,同理汽设计也得改, 也就是整个设计乎都得改
我们尝试换种思路, 我们先设计汽的概样,然后根据汽的样来设计,根据来设计底盘,最后根据底盘来设计轮. 这时候,依赖关系就倒置过来了:轮依赖底盘, 底盘依赖,依赖汽
这就类似我们打造辆完整的汽, 如果所有的配件都是造,那么当客需求发改变的时候,
如轮胎的尺不再是原来的尺了,那我们要动来改了,但如果我们是把轮胎外包出去,那
么即使是轮胎的尺发变变了,我们只需要向代理下订单就了,我们是不需要出的.

如何来实现呢:
我们可以尝试不在每个类中创建下级类,如果创建下级类就会出现当下级类发改变操作,
也要跟着修改.
此时,我们只需要将原来由创建的下级类,改为传递的式(也就是注的式),因为我们不
需要在当前类中创建下级类了,所以下级类即使发变化(创建或减少参数),当前类本也需修

  • 改任何代码,这样就完成了程序的解耦

IoC 程序开发

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

![](https://wy-static.wenxiaobai.com/chat-rag-image/8813074233339579121)
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(framewoek);
        car.run();    
    }
    
    /**
     * 汽车对象
     */
    static class Car {  
        private Framework framework;  
        
        public Car(Framework framework) {  
            framework = new Framework();  
            System.out.println("framework init...");  
        } 
        public void run() {  
            System.out.println("car run...");  
        }  
    }
    /**
     * 车身类
     */
     static class Framework {  
        private Bottom bottom;  
        
        public Framework(Bottom bottom) {  
            bottom = new Bottom();  
            System.out.println("bottom init...");  
        }  
    }   
    /**
     * 底盘类
     */
     static class Bottom {  
        private Tire tire;  
      
        public Bottom(Tire tire) {  
            tire = new Tire();  
            System.out.println("tire init...");  
        }  
    }
    /**
     * 轮胎类
     */
     public class Tire {  
        private int size = 21;  
      
        public Tire(int size) {  
            this.size = size;
            System.out.println("tire size:" +size);  
        }  
    }
}
  • 代码经过以上调整,论底层类如何变化,整个调链是不做任何改变的,这样就完成了代码之间的解耦,从实现了更加灵活、通的程序设计了。

IoC 的优势

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

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

这样的话, 即使依赖类发任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是IoC的实现思想。

学到这, 我们概就知道了什么是控制反转了, 那什么是控制反转容器呢, 也就是IoC容器

这部分代码, 就是IoC容器做的作.

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

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

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

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号