Spring Ioc源码引入:什么是IoC,IoC解决了什么问题
Spring Ioc源码引入:什么是IoC,IoC解决了什么问题
什么是IoC
用一个故事举例:
小陈想开一家咖啡店,于是独自创业。找咖啡豆供应商、买咖啡机、招员工,样样都要自己来。开店成本很高。后来,小陈选择加盟连锁咖啡店。总部帮他对接供应商、提供咖啡机,还负责员工培训。小陈只需按流程做好咖啡服务顾客,经营轻松许多。
独立开店时,小陈事事操心,就像没有 IOC,系统耦合度高,难以维护与扩展。加盟后,总部统一管理资源,小陈专注核心业务,如同引入 IOC,降低耦合度,经营变得高效。
上面的故事你可能还无法对应到程序开发场景中,下面我们进行Java代码模拟
用Java代码模拟:
- 没有IOC
如下可以看到构造一个咖啡店,需要依赖服务员、清洁工、咖啡豆供应商、以及咖啡机
所以,当我们需要开一个咖啡店的时候,需要自己处理好这些依赖,对应到下面代码,我们自己找到合适的服务员、清洁工、咖啡豆供应商、以及咖啡机,然后开店:
public class CoffeeShop {
// 服务员
private Waiter waiter;
// 清洁工
private Cleaner cleaner;
// 咖啡豆供应商
private CoffeeBeansSupplier coffeeBeansSupplier;
// 咖啡机
private CoffeeMachine coffeeMachine;
public CoffeeShop(Waiter waiter,
Cleaner cleaner,
CoffeeBeansSupplier coffeeBeansSupplier,
CoffeeMachine coffeeMachine) {
this.waiter = waiter;
this.cleaner = cleaner;
this.coffeeBeansSupplier = coffeeBeansSupplier;
this.coffeeMachine = coffeeMachine;
}
public void saleCoffee() {
}
}
public class BootStrap {
public static void main(String[] args) {
// 我们自己找到合适的服务员
Waiter waiter = null;
// 我们自己找到合适的清洁工
Cleaner cleaner = null;
// 我们自己找到合适的咖啡供应商
CoffeeBeansSupplier coffeeBeansSupplier = null;
// 我们自己找到合适的咖啡机
CoffeeMachine coffeeMachine = null;
// 开店,构造自己的咖啡店
CoffeeShop cacheShop = new CoffeeShop(waiter, cleaner, coffeeBeansSupplier, coffeeMachine);
// 开始售卖咖啡
cacheShop.saleCoffee();
}
}
- 具备IOC(以SpringBoot 为例)
首先我们使用Autowired注解来描述CoffeeShop依赖服务员、清洁工、咖啡豆供应商、以及咖啡机
public class CoffeeShop {
// 表明我们需要服务员
@Autowired
private Waiter waiter;
// 表明我们需要清洁工
@Autowired
private Cleaner cleaner;
// 表明我们需要咖啡供应
@Autowired
private CoffeeBeansSupplier coffeeBeansSupplier;
// 表明我们需要咖啡机器
@Autowired
private CoffeeMachine coffeeMachine;
public void saleCoffee() {
}
}
@SpringBootApplication
public class BootStrap {
public static void main(String[] args) {
// ctx就如同总部
ConfigurableApplicationContext ctx = SpringApplication.run(BootStrap.class, args);
// ctx.getBean就如同总部处理好各种依赖(服务员、清洁工、咖啡豆供应商、以及咖啡机)
CoffeeShop shop = ctx.getBean(CoffeeShop.class);
// 我们可以直接进行开店
shop.saleCoffee();
}
}
再理解IoC:
IOC的全称是Inversion of Control,即控制反转。控制反转,从字面理解,就是控制权的反转。
没有IOC:传统的程序流程是由开发者自己控制的,比如对象A需要对象B,那么A会直接创建B或者通过工厂类获取B的实例。这种情况下,控制权在A手里
有了IOC:而IoC则是将这种控制权交给外部容器或框架,由外部来管理对象的创建和依赖关系。比如,通过依赖注入,对象A不需要自己创建B,而是由外部容器将B注入到A中。这样,控制权就从A转移到了容器,这就是所谓的反转。
不同的理解:有的人也认为是从程序员手里,转移到IOC容器
结合上面的例子:
没有IOC:咖啡店需要的各种依赖,需要小陈自己处理,自己找咖啡豆供应商等等,然后开店
有了IOC:咖啡店的所有配置,由总部这个容器来统一安排
IoC解决了什么问题
IOC(控制反转)主要解决对象间耦合度过高的问题。在传统编程中,对象直接通过new关键字创建依赖对象,导致代码高度耦合,难以维护和扩展。IOC将对象的创建、依赖管理和生命周期交给外部容器,从而解耦组件。
在上面场景中,总部就是我们的IOC容器,它管理了众多不同的咖啡供应商,咖啡机,可以根据你开店的需求,为你的咖啡店进行装配。
- 那么现在思考一下如何实现IOC呢?
IOC容器需要给CoffeeShop自动的填充依赖——依赖注入(Dependency Injection, DI)
何为依赖:
如果一个对象A缺少另外一个对象B那么将无法工作(方法不可用)那么我们可以说,A依赖B
那么如何实现依赖注入呢?
如何实现IoC or DI
3.1 如何描述依赖
首先需要清楚如何描述依赖
在Java中一般有三种方式:
字段+注解
如下面代码中的waiter,标注@Autowired说明这个字段需要进行依赖注入构造器
如下面的构造方法,每一个方法参数都可以视为CoffeeShop在描述自己依赖哪些外部组件setter方法
如下面的setCleaner,同样是实验@Autowired来说明自己依赖Cleaner
public class CoffeeShop {
@Autowired //字段+注解
private Waiter waiter;
private Cleaner cleaner;
private CoffeeBeansSupplier coffeeBeansSupplier;
private CoffeeMachine coffeeMachine;
// 构造器
public CoffeeShop(Waiter waiter,
Cleaner cleaner,
CoffeeBeansSupplier coffeeBeansSupplier,
CoffeeMachine coffeeMachine) {
this.waiter = waiter;
this.cleaner = cleaner;
this.coffeeBeansSupplier = coffeeBeansSupplier;
this.coffeeMachine = coffeeMachine;
}
@Autowired // setter方法
public void setCleaner(Cleaner cleaner) {
this.cleaner = cleaner;
}
}
当然Spring还可以使用注解和工厂方法,这里为了方便粉丝理解,不做过多扩展。
3.2 如何进行依赖注入
如上,我们完成了描述依赖的过程,那么如何进行依赖注入呢?
在java一般来说有两种方式:反射和生成代码
反射:
java提供的反射,允许程序在 运行时 动态地获取类的信息(如类名、方法、字段、注解等),并能直接操作类或对象(如创建实例、调用方法、访问私有字段)反射调用方法:可以用于实现基于构造器和setter方法的依赖注入,将依赖项作为参数进行传入,然后反射调用方法即可
反射访问字段:可以用于实现基于字段的依赖注入,找到匹配要求的对象,反射为字段赋值即可
生成代码:
例如 Google 维护Dagger 2 ,会在编译时依赖注入框架,直接通过代码生成实现依赖注入,无需反射或动态代理,启动性能更佳。生成代码的方式在Go语言中运用广泛,主要是Go提供的反射能力没有java那么强大,加上Go强调云原生,对部署速度有较高要求
其中Spring Ioc使用的是反射
Spring Ioc源码学习引入
每个 Spring 开发者都踩过的「坑」
为什么要啃 Spring IoC 源码?
- 面试「灵魂拷问」高频区
- “Spring 如何解决循环依赖?”
- “BeanFactory 和 ApplicationContext 的区别?”
- “@Autowired 和 @Resource 注入原理有何不同?”
绝大部分 Java 高级岗位面试会深挖 Spring 源码实现。 仅靠八股文背诵,难以应对灵活追问。
- 日常开发中的「未解之谜」
- 为什么 @Transactional 注解有时失效?
- 如何定制 Bean 的生命周期回调?
- 配置文件加载的优先级到底怎么定?
源码能让你从「玄学调试」进阶到「精准打击」。
- 架构思维跃迁的关键阶梯
Spring 的设计融合了工厂模式、模板方法、策略模式等经典设计模式,其代码是「教科书级」的架构范本。
读源码 = 站在巨人肩上,学习如何设计高扩展、低耦合的系统。
>>>点击去关注<<<
Spring Ioc源码引入:什么是IoC,IoC解决了什么问题的更多相关文章
- Spring系列(三):Spring IoC源码解析
一.Spring容器类继承图 二.容器前期准备 IoC源码解析入口: /** * @desc: ioc原理解析 启动 * @author: toby * @date: 2019/7/22 22:20 ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- Spring Ioc源码分析系列--Ioc的基础知识准备
Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...
- Spring IOC源码研究笔记(2)——ApplicationContext系列
1. Spring IOC源码研究笔记(2)--ApplicationContext系列 1.1. 继承关系 非web环境下,一般来说常用的就两类ApplicationContext: 配置形式为XM ...
- Spring的IOC源码分析
Spring IOC 容器源码分析 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不 ...
- Spring IoC源码解析——Bean的创建和初始化
Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...
- [spring源码学习]六、IOC源码-BeanFactory和factory-bean
一.代码实例 在我们分析spring的IOC源码的时候,发现除了配置标准的bean,并且通过getBean(beanName)的方法获取到一个bean的实例外,似乎还有这不少其他获取的方法,例如在第四 ...
- Spring:源码解读Spring IOC原理
Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...
- 深入Spring IOC源码之ResourceLoader
在<深入Spring IOC源码之Resource>中已经详细介绍了Spring中Resource的抽象,Resource接口有很多实现类,我们当然可以使用各自的构造函数创建符合需求的Re ...
- 框架源码系列六:Spring源码学习之Spring IOC源码学习
Spring 源码学习过程: 一.搞明白IOC能做什么,是怎么做的 1. 搞明白IOC能做什么? IOC是用为用户创建.管理实例对象的.用户需要实例对象时只需要向IOC容器获取就行了,不用自己去创建 ...
随机推荐
- swiper8.x在vue中的wtf
首先我是想开启鼠标滚动的效果,在官网上发现如下说法 引入就引入吧,引入路径还不说,在网上看其他教程发现路径是 引入完了,怎么办呢,又不会了,官网没有教程,网上的教程全是关于vue-awesome-sw ...
- error setting certificate verify locations: CAfile: C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt CApath: none
这个问题是因为git配置里crt证书的路径不正确导致的. 这个路径配置是在C:\Program Files\Git\etc\gitconfig中,应该所有人的配置都在这里 [diff "as ...
- Linux - centos6忘记root密码怎么办?
Linux的root密码修改不像Windows的密码修改找回,Windows的登录密码忘记需要介入工具进行解决.CentOS6和CentOS7的密码方法也是不一样的,具体如下 1.开机按esc 2 ...
- python基础-函数(函数参数、返回值、执行、传参、作用域、函数名)
前言 !!!注意:本系列所写的文章全部是学习笔记,来自于观看视频的笔记记录,防止丢失.观看的视频笔记来自于:哔哩哔哩武沛齐老师的视频:2022 Python的web开发(完整版) 入门全套教程,零基础 ...
- 震惊!Manus邀请码炒到5万元一个!附免费获取Manus邀请码两种方式
在AI技术蓬勃发展的当下,一款名为Manus的产品掀起了行业巨浪.本文将深入剖析这款全球首款通用AI智能体,从它的惊艳亮相.独特功能,到其性能突破.模式限制,以及在AI领域的深远意义,全方位带大家了解 ...
- Windows编程----进程:环境变量
什么是系统环境变量 每台计算机针对当前用户和系统中所有用户分别提供了两个环境变量设置,通过计算机属性>环境变量的界面,我们可以查看当前这台计算机上的所有环境变量,这些环境变量都是key-valu ...
- pandas 判断列是否包含某个字符串
亲测第二种好用 in 语句 不包含使用not in food = df['日期'].values.tolist() if '休息' in food: print(food) if df['共计小时'] ...
- ModuleNotFoundError: No module named '_sqlite3' when Python3
前言 运行 python 报错:ModuleNotFoundError: No module named '_sqlite3' 解决 重新编译安装 python ./configure --enabl ...
- vue 保留两位小数
前言 有时候我们需要对各种数值进行保留位数,以便于更好的展示. Html部分 template中这样使用,需要处理的字段名,再加上过滤器方法 <div class="text prim ...
- PaddleOCR学习笔记3-通用识别服务
今天优化了下之前的初步识别服务的python代码和html代码. 采用flask + paddleocr+ bootstrap快速搭建OCR识别服务. 代码结构如下: 模板页面代码文件如下: uplo ...