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

文章目录

在前面中,我们学习了 Spring Boot 和 Spring MVC 的开发,可以完成一些基本功能的开发了,但是什么是 Spring 呢?Spring,Spring Boot,SpringMVC 又有什么关系呢?

Spring 是什么

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

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

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

什么是容器

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

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

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

什么是 IoC

IoCSpring 的核心思想,也是常见的面试题。其实我们在前面已经使用过了 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) {
		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 程序开发

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

复制代码
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 控制并创建了 FrameworkFramework 创建并创建了 Bottom,依次往下,改进之后的控制权发的反转,不再是使对象创建并控制依赖对象了,是把依赖对象注将当前对象中,依赖对象的控制权不再由当前类控制了.

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

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

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

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

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

    就可以了

  2. 我们在创建实例的时候不需要了解其中的细节, 降低了使资源双的依赖程度, 也就是耦合度。Spring 就是种 IoC 容器, 帮助我们来做了这些资源管理.

相关推荐
豆瓣鸡8 分钟前
封装 API 请求日志切面——从注解定义到 Starter 自动装配
java·开发语言·spring boot
高明珠17 分钟前
麒麟 V10 SP1 踩坑:`./startup.sh` 报“解释器错误: 权限不够“,根因是 KySec
后端
用户83580861879128 分钟前
基于Redis的分布式锁优化实践:从Redlock到自适应自旋的实现与思考
后端
掘金者阿豪34 分钟前
想让短视频自动生产?用MoneyPrinterTurbo搭一个远程可控的AI创作平台
后端
掉鱼的猫43 分钟前
把 OpenAPI 接入 Agent Harness:零代码让 Agent 听懂你的 REST API
java·llm·agent
梨子同志1 小时前
开发工具
前端·后端
梨子同志1 小时前
Java
后端
lzhcoder1 小时前
Spring Boot 集成 Kafka:先跑通 Demo,再避开那 80% 的人踩过的坑
java·kafka
像我这样帅的人丶你还1 小时前
Java 后端详解(六):Maven 与本地开发指南
前端·后端
tonydf1 小时前
.NET 项目集成可观测性:从架构思考到落地实践
运维·后端