Spring IOC 到底是什么?

简介: IOC(控制反转)是一种设计思想,主要用于解耦代码,简化依赖管理。其核心是将对象的创建和管理交给容器处理,而非由程序直接硬编码实现。通过IOC,开发者无需手动new对象,而是由框架负责实例化、装配和管理依赖对象。常见应用如Spring框架中的BeanFactory和ApplicationContext,它们实现了依赖注入和动态管理功能,提升了代码的灵活性与可维护性。

什么是IOC

简单的说:

IOC就是构建和管理依赖的容器

咱们暂且放下控制反转这个拗口的词。

没有IOC的年代

在IOC诞生之前,我们是如何写业务代码的呢? 如下面所示:

java

体验AI代码助手

代码解读

复制代码

public class A {
    
}

public class B {
    
    private A a = new A();
}


当然上述是一段伪代码。

维护的困局

代码能按业务拆分成多个不同的类已经是不错的写法了,但是到了要增加逻辑的时候就麻烦了。

你得对A或者B进行修改,这样维护起来还是不够优雅的。

于是你对此进行了一些设计:

java

体验AI代码助手

代码解读

复制代码

interface A {
    void method();
}

public class AImpl implents A { 
    void method(){
        // todo
    }
}

public class B {
    
    private final A a;  
        
    public B(A a){
        this.a = a; // 传入对应的实现    
    }
    
}

这样在需要新增逻辑的时候只要写一个新的实现类就行了,不必回去修改AImpl了。

依赖处理的困局

到这一步我们发现B对A存在依赖,这个依赖由外部传入,也就是说新增逻辑我们必须得修改传入依赖的地方。

java

体验AI代码助手

代码解读

复制代码

new B(new AImpl());

这里可能就会修改为: 

new B(new BImpl());

上面暴露了2个比较明显的问题:

  1. 每次调整都可能会修改依赖  => 依赖的管理问题
  2. 每次都是new一个依赖进去,非常浪费内存  => 依赖的构建问题

这时,你能设计出一个办法处理这种问题吗?

IOC的诞生

分析

我们一步一步来分析下这2个问题,如果换做是人来处理这些东西会怎么处理呢?

第一步,我们必须得知道哪个类依赖哪个类,也就是说要有一个提供依赖信息的地方。 第二步,得知依赖信息了,我们就得new个出来给他。

那么我们定义一下这2步,第一步可以称之为依赖信息的获取,第二步可以称之为依赖的管理。

如何处理问题

  • 依赖信息的获取
  1. XML配置形式
  2. Java注解方式
  3. 其他形式

信息可以记录在任何地方,任何形式,但我们得找到一个最适应当下的方式。 聪明的你应该已经想到了,我们先定义一个接口,做成一个策略模式,不同形式的使用不同的加载策略。

  • 依赖的管理
  1. 实例化
  2. 依赖处理
  3. 其他前置后置处理

我们可以直接使用反射来进行实例化和依赖处理,当然实例化和依赖处理最好也留好接口。

这里我就不写代码演示了,目的是要大家明白IOC的主要2个功能即:

  1. 依赖的构建
  2. 依赖的管理

Spring提供的IOC容器

Spring提供了2个IOC容器:

  1. BeanFactory

基础IOC能力,只有Bean的构建和管理

  1. ApplicationContext

基于BeanFactory,增加了其他功能

简而言之,ApplicationContext提供了更多的可用可扩展的功能。

BeanFactory如何管理依赖

DefaultListableBeanFactory 类是BeanFactory的一个默认实现类,有完整的bean构建管理功能。

java

体验AI代码助手

代码解读

复制代码

DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();


RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(AreaApi.class); // 转为统一的Bean的定义信息类

defaultListableBeanFactory.registerBeanDefinition("A",rootBeanDefinition);  // 向容器中注入定义  其实就是添加进一个map里 

defaultListableBeanFactory.getBean("A");


private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);  // 这里就是存放所有bean定义的地方 是DefaultListableBeanFactory的一个属性。

ApplicationContext如何管理依赖

AnnotationConfigApplicationContext <= GenericApplicationContext <= AbstractApplicationContext <= ApplicationContext

通过整个继承链来看,最终是实现了ApplicationContext的。

java

体验AI代码助手

代码解读

复制代码

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ValidatorConfiguration.class);

ValidatorConfiguration bean = annotationConfigApplicationContext.getBean(ValidatorConfiguration.class);

其实追寻源码可以看到在==GenericApplicationContext==类中是加载了 DefaultListableBeanFactory

java

体验AI代码助手

代码解读

复制代码




public GenericApplicationContext() {
    this.customClassLoader = false;
    this.refreshed = new AtomicBoolean();
    this.beanFactory = new DefaultListableBeanFactory(); // 构造方式中 直接 new 了基础IOC容器
}

总结

整个IOC的流程可以归纳为:

获取bean的信息 => 保存起来 => 实例化 => 处理依赖 => 返回实例

其余功能无非是在这几个流程上加前置或者后置处理。

在最后解释一下控制反转怎么理解:

其实就是由人管理依赖也就是new的过程交给了程序,控制权交出去了,也就是控制权反转了。

spring的源码过于庞大了,如果有兴趣可以自行研究,这里我们只关注Spring最重要的部分就可以了。


转载来源:https://juejin.cn/post/7057051278836236324

相关文章
|
2月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
2月前
|
机器学习/深度学习 设计模式 人工智能
深度解析Agent实现,定制自己的Manus
文章结合了理论分析与实践案例,旨在帮助读者系统地认识AI Agent的核心要素、设计模式以及未来发展方向。
948 100
深度解析Agent实现,定制自己的Manus
|
3月前
|
人工智能 IDE API
10行代码,实现你的专属阿里云OpenAPI MCP Server
本文介绍如何用10行Python代码创建专属阿里云OpenAPI MCP Server。针对传统MCP Server工具固化、开发复杂等问题,提出借助alibaba-cloud-ops-mcp-server实现灵活拓展的方案。通过配置服务与API名称,运行简短代码即可生成支持SSE连接的MCP Server。用户无需深入了解阿里云OpenAPI细节,大幅降低开发门槛。未来将探索通用工具设计,实现固定工具调用任意API,进一步提升灵活性与效率。
|
17天前
|
自然语言处理 前端开发 Java
JBoltAI 框架完整实操案例 在 Java 生态中快速构建大模型应用全流程实战指南
本案例基于JBoltAI框架,展示如何快速构建Java生态中的大模型应用——智能客服系统。系统面向电商平台,具备自动回答常见问题、意图识别、多轮对话理解及复杂问题转接人工等功能。采用Spring Boot+JBoltAI架构,集成向量数据库与大模型(如文心一言或通义千问)。内容涵盖需求分析、环境搭建、代码实现(知识库管理、核心服务、REST API)、前端界面开发及部署测试全流程,助你高效掌握大模型应用开发。
105 5
|
2月前
|
缓存 Java Nacos
如何优雅上线、下线?原来 大厂应用 是这样 优雅发布的!
如何优雅上线、下线?原来 大厂应用 是这样 优雅发布的!
如何优雅上线、下线?原来 大厂应用 是这样 优雅发布的!
|
15天前
|
Python
Python f-strings:让字符串格式化更简洁高效!
Python f-strings:让字符串格式化更简洁高效!
143 81
|
17天前
|
消息中间件 机器学习/深度学习 Java
java 最新技术驱动的智能教育在线实验室设备管理与实验资源优化实操指南
这是一份基于最新技术的智能教育在线实验室设备管理与实验资源优化的实操指南,涵盖系统搭建、核心功能实现及优化策略。采用Flink实时处理、Kafka消息队列、Elasticsearch搜索分析和Redis缓存等技术栈,结合强化学习动态优化资源调度。指南详细描述了开发环境准备、基础组件部署、数据采集与处理、模型训练、API服务集成及性能调优步骤,支持高并发设备接入与低延迟处理,满足教育机构数字化转型需求。代码已提供下载链接,助力快速构建智能化实验室管理系统。
82 44
|
8天前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
54 13
|
6天前
|
编解码 物联网 开发者
FLUX.1 Kontext 的全生态教程来啦!AIGC专区在线试玩!
Flux.1 Kontext [dev] 开源模型大家都用上了吗?小编汇总了3个使用教程,打包送上!
264 1