什么是 Spring IOC?

Spring IOC(控制反转)详解

一、什么是 IOC

IOC(Inversion of Control,控制反转)是一种设计思想,不是什么技术实现。它指的是将对象的创建、管理和依赖关系的控制权从程序代码本身转移到外部容器(Spring 容器)。

传统方式 vs IOC

传统方式(程序控制):

publicclassUserService{privateUserDaouserDao=newUserDao();// 自己创建依赖对象publicvoidaddUser(){userDao.save();}}

IOC 方式(容器控制):

publicclassUserService{@AutowiredprivateUserDaouserDao;// 容器注入依赖对象publicvoidaddUser(){userDao.save();}}

二、IOC 的核心概念

1. 控制反转

  • 控制:指对象创建、依赖管理的控制权
  • 反转:从程序代码反转到外部容器

2. 依赖注入(DI,Dependency Injection)

DI 是 IOC 的实现方式,指容器在创建对象时,自动将依赖对象注入到目标对象中。

3. IOC 容器

Spring 提供的容器实现,负责管理 Bean 的生命周期和依赖关系。

三、Spring IOC 容器

1. 两个核心接口

// BeanFactory:基础容器,提供基本的 IOC 功能publicinterfaceBeanFactory{ObjectgetBean(Stringname);<T>TgetBean(Class<T>requiredType);booleancontainsBean(Stringname);// ...}// ApplicationContext:高级容器,扩展了更多功能publicinterfaceApplicationContextextendsBeanFactory{// 国际化支持StringgetMessage(Stringcode,Object[]args,Localelocale);// 资源加载ResourcegetResource(Stringlocation);// 事件发布voidpublishEvent(ApplicationEventevent);// ...}

2. 常见的实现类

// 1. ClassPathXmlApplicationContext:从类路径加载配置ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");// 2. FileSystemXmlApplicationContext:从文件系统加载配置ApplicationContextcontext=newFileSystemXmlApplicationContext("D:/config/applicationContext.xml");// 3. AnnotationConfigApplicationContext:基于注解的配置ApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);// 4. WebApplicationContext:Web 应用专用// 在 Spring Boot 中自动创建

四、Bean 的定义方式

1. XML 配置方式

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义 Bean --><beanid="userService"class="com.example.UserService"><!-- 构造器注入 --><constructor-argref="userDao"/><!-- 属性注入 --><propertyname="name"value="张三"/></bean><beanid="userDao"class="com.example.UserDao"/></beans>

2. 注解方式(推荐)

// 1. @Component:通用组件@ComponentpublicclassUserService{@AutowiredprivateUserDaouserDao;}// 2. @Service:服务层@ServicepublicclassUserService{@AutowiredprivateUserDaouserDao;}// 3. @Repository:数据访问层@RepositorypublicclassUserDao{publicvoidsave(){// ...}}// 4. @Controller:控制层@ControllerpublicclassUserController{@AutowiredprivateUserServiceuserService;}// 5. @Configuration:配置类@Configuration@ComponentScan("com.example")publicclassAppConfig{@BeanpublicUserServiceuserService(){returnnewUserService(userDao());}@BeanpublicUserDaouserDao(){returnnewUserDao();}}

五、依赖注入的方式

1. 构造器注入(推荐)

@ServicepublicclassUserService{privatefinalUserDaouserDao;// Spring 4.3+ 单个构造器可省略 @Autowired@AutowiredpublicUserService(UserDaouserDao){this.userDao=userDao;}}

优点:

  • 保证依赖不可变(final)
  • 保证对象初始化完成
  • 更容易测试

2. Setter 注入

@ServicepublicclassUserService{privateUserDaouserDao;@AutowiredpublicvoidsetUserDao(UserDaouserDao){this.userDao=userDao;}}

优点:

  • 灵活,可以在运行时修改
  • 适合可选依赖

3. 字段注入

@ServicepublicclassUserService{@AutowiredprivateUserDaouserDao;}

缺点:

  • 不能使用 final
  • 容易导致空指针
  • 不利于测试

4. 方法注入

@ServicepublicclassUserService{privateUserDaouserDao;@Autowiredpublicvoidinit(UserDaouserDao){this.userDao=userDao;}}

六、Bean 的作用域

// 1. singleton(默认):单例,整个容器只有一个实例@Scope("singleton")publicclassUserService{}// 2. prototype:原型,每次获取都创建新实例@Scope("prototype")publicclassUserService{}// 3. request:Web 应用,每个请求一个实例@Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.TARGET_CLASS)publicclassUserService{}// 4. session:Web 应用,每个会话一个实例@Scope(value=WebApplicationContext.SCOPE_SESSION,proxyMode=ScopedProxyMode.TARGET_CLASS)publicclassUserService{}// 5. application:Web 应用,ServletContext 生命周期@Scope(value=WebApplicationContext.SCOPE_APPLICATION,proxyMode=ScopedProxyMode.TARGET_CLASS)publicclassUserService{}

七、Bean 的生命周期

@ComponentpublicclassUserServiceimplementsBeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{// 1. 实例化(构造器)publicUserService(){System.out.println("1. 实例化");}// 2. 设置属性@AutowiredprivateUserDaouserDao;// 3. BeanNameAware@OverridepublicvoidsetBeanName(Stringname){System.out.println("3. BeanNameAware.setBeanName: "+name);}// 4. BeanFactoryAware@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory){System.out.println("4. BeanFactoryAware.setBeanFactory");}// 5. ApplicationContextAware@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext){System.out.println("5. ApplicationContextAware.setApplicationContext");}// 6. BeanPostProcessor - 前置处理@PostConstructpublicvoidpostConstruct(){System.out.println("6. @PostConstruct");}// 7. InitializingBean@OverridepublicvoidafterPropertiesSet(){System.out.println("7. InitializingBean.afterPropertiesSet");}// 8. 自定义初始化方法@Bean(initMethod="init")publicvoidinit(){System.out.println("8. 自定义初始化方法");}// Bean 可以使用了// 9. PreDestroy@PreDestroypublicvoidpreDestroy(){System.out.println("9. @PreDestroy");}// 10. DisposableBean@Overridepublicvoiddestroy(){System.out.println("10. DisposableBean.destroy");}// 11. 自定义销毁方法@Bean(destroyMethod="cleanup")publicvoidcleanup(){System.out.println("11. 自定义销毁方法");}}

八、IOC 容器启动流程

// 1. 创建容器ApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);// 内部流程:// 1.1 扫描配置类,解析 Bean 定义// 1.2 注册 Bean 定义到 BeanDefinitionRegistry// 1.3 实例化单例 Bean(非懒加载)// 1.4 执行依赖注入// 1.5 执行初始化回调// 1.6 容器启动完成

九、自动装配(@Autowired)

1. 按类型装配

@AutowiredprivateUserDaouserDao;// 按类型查找

2. 按名称装配

@Autowired@Qualifier("userDaoImpl")// 指定 Bean 名称privateUserDaouserDao;

3. 可选依赖

@Autowired(required=false)// 不存在也不报错privateUserDaouserDao;

4. 集合注入

@AutowiredprivateList<UserDao>userDaoList;// 注入所有 UserDao 类型@AutowiredprivateMap<String,UserDao>userDaoMap;// Bean名称 -> Bean实例

十、条件化注册 Bean

// 1. @Conditional@ConfigurationpublicclassAppConfig{@Bean@Conditional(WindowsCondition.class)// 满足条件才注册publicUserServicewindowsService(){returnnewWindowsService();}@Bean@Conditional(LinuxCondition.class)publicUserServicelinuxService(){returnnewLinuxService();}}// 2. 常用条件注解@ConditionalOnClass(DataSource.class)// 类路径存在@ConditionalOnMissingBean(DataSource.class)// 容器中不存在@ConditionalOnProperty(name="app.enabled",havingValue="true")// 配置属性@ConditionalOnExpression("${app.enabled:true}")// SpEL 表达式

十一、IOC 的优势

1. 解耦

// 不再需要手动创建和管理对象// 对象之间的关系由容器维护

2. 便于测试

// 可以轻松注入 Mock 对象@TestpublicvoidtestUserService(){UserDaomockDao=mock(UserDao.class);UserServiceservice=newUserService(mockDao);// 测试...}

3. 配置化管理

// 通过配置文件或注解管理对象// 便于维护和修改

4. AOP 支持

// IOC 容器管理对象,便于实现 AOP@Aspect@ComponentpublicclassLoggingAspect{@Before("execution(* com.example.*.*(..))")publicvoidlogBefore(){// ...}}

十二、总结

Spring IOC 的核心价值:

  1. 控制反转:将对象创建和依赖管理的控制权交给容器
  2. 依赖注入:容器自动将依赖注入到目标对象
  3. 松耦合:对象之间通过接口依赖,降低耦合度
  4. 易测试:便于单元测试和集成测试
  5. 易维护:集中管理对象,便于配置和修改

最佳实践:

  • 优先使用构造器注入
  • 使用注解配置(@Component、@Service 等)
  • 合理使用 Bean 的作用域
  • 理解 Bean 的生命周期,合理使用初始化和销毁回调
  • 避免循环依赖,必要时使用 @Lazy

Spring IOC 是 Spring 框架的基石,理解它对于掌握 Spring 至关重要!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1216088.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring 中的 DI 是什么?

Spring 中的 DI&#xff08;Dependency Injection&#xff0c;依赖注入&#xff09;是 Spring 框架的核心特性之一&#xff0c;也是控制反转&#xff08;IoC&#xff0c;Inversion of Control&#xff09;原则的具体实现。 什么是 DI&#xff1f; 依赖注入是一种设计模式&…

深入浅出了解生成模型-8:生成加速策略概述 - Big-Yellow

扩散模型生成加速策略主要包括加速框架优化、Cache策略及量化技术。加速框架方面,可通过指定attention计算后端(如flash_attn)、torch.compile编译、torch.channels_last优化内存访问,或使用xFormers加速attention…

P1102 A-B 数对(lower_bound函数)

点击查看代码 #include<bits/stdc++.h> using namespace std;typedef long long LL; const int N=2e5+10; LL a[N]; LL c; int n;int main() {ios::sync_with_stdio(0),cin.tie(0);cin>>n>>c;for(in…

Java毕设选题推荐:基于springboot的农企信息管理平台设计与开发基于SpringBoot+Vue农企信息管理平台设计与开发【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【ISAC】5G NR-PRS赋能6G多基地ISAC:LoS/NLoS混合场景定位精度突破28%!【附MATLAB代码】

5G NR-PRS赋能6G多基地ISAC&#xff1a;LoS/NLoS混合场景定位精度突破28%&#xff01; 在第六代移动通信&#xff08;6G&#xff09;的技术演进蓝图中&#xff0c;集成感知与通信&#xff08;ISAC&#xff09;作为“通感一体”的核心技术&#xff0c;正重构无线系统的应用边界…

【电力系统】基于角度-电压耦合引起的稳定性衰减:波德型基本性能限制分析附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#…

【课程设计/毕业设计】基于SpringBoot+Vue农企信息管理平台设计与开发基于springboot的农企信息管理平台设计与开发【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Java计算机毕设之基于springboot的种植基地农业信息管理系统的设计与实现基于springboot的农企信息管理平台设计与开发(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【SSVEP】基于SSVEP检测频率导向脑活动的VR实验附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#…

基于深度学习YOLOv10的水果分类检测系统(YOLOv10+YOLO数据集+UI界面+Python项目源码+模型)

一、项目介绍 摘要 本项目基于YOLOv10深度学习框架&#xff0c;开发了一套高精度水果多目标分类检测系统&#xff0c;能够同时识别六种常见水果&#xff1a;苹果(Apple)、香蕉(Banana)、芒果(Mango)、橙子(Orange)、菠萝(Pineapple)和西瓜(Watermelon)。系统通过对水果图像进…

我用 Claude Code 给自己打造了个人助理,他将比我更了解我自己

我们都知道和 AI 对话最大的难点就是,AI 每次都会忘记你的上下文。 好比和 DeepSeek 沟通,每一次都要新开一个对话窗口,这就会导致,每次你在和 DeepSeek 聊天的时候,都需要重复解释一下,你的背景,你是谁。 如何…

MiniCPM4-0.5B-QAT-Int4-GPTQ-format 小显存llm

MiniCPM4-0.5B-QAT-Int4-GPTQ-format 模型库 from modelscope import AutoTokenizer from vllm import LLM, SamplingParamsmodel_name "OpenBMB/MiniCPM4-0.5B-QAT-Int4-GPTQ-format" prompt [{"role": "user", "content": "…

虚拟桌宠工作学习实际收益

工作、学习的收益计算 倍率调整为 1 时,工作、学习的基础数据即为基础值,收益计算方式和倍率调整大于 1 时计算方式并不相同,主要区别在于食物口渴心情的消耗不同。 当倍率调整大于 1 时,工作的数据如下: 倍率调整…

强烈安利9个AI论文软件,专科生轻松搞定毕业论文!

强烈安利9个AI论文软件&#xff0c;专科生轻松搞定毕业论文&#xff01; AI 工具的崛起&#xff0c;让论文写作不再难 对于专科生来说&#xff0c;撰写毕业论文往往是一道难以逾越的门槛。从选题、查找资料到撰写初稿、反复修改&#xff0c;每一个环节都可能让人感到力不从心。…

计算机Java毕设实战-基于springboot的农企商品产品信息管理平台设计与开发【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

基于51单片机的水质检测 PH TDS 温度+浊度+报警

目录 基于51单片机的水质检测系统设计硬件组成软件设计校准与优化扩展功能 源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 基于51单片机的水质检测系统设计 该系统以51单片机为核心&#xff0c;集成多种传感器模块&#xff0c;实时监…

基于51单片机的水质检测 PH 浊度 温度 蓝牙 报警

目录 基于51单片机的水质检测系统设计硬件组成模块软件设计要点系统调试注意事项扩展功能方向 源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 基于51单片机的水质检测系统设计 系统概述 该系统以51单片机为核心&#xff0c;集成PH值传…

寒假2

今天本来想早睡会,但是睡不着。

基于51单片机的汽车胎压检测系统 蓝牙 气压 温度

目录 51单片机汽车胎压检测系统概述核心功能模块系统工作流程关键代码示例&#xff08;气压读取&#xff09;硬件设计要点应用场景 源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 51单片机汽车胎压检测系统概述 基于51单片机的汽车胎…