【Spring基础】关于Spring IoC的那些事

在这里插入图片描述

文章目录

  • 一、如何理解IoC
    • 1.1 Spring IOC 概述
    • 1.2 IoC 是什么
  • 二、Ioc 配置的方式
    • 2.1 xml 配置
    • 2.2 Java 配置
    • 2.3 注解配置
  • 三、依赖注入的方式
    • 3.1 setter方式
    • 3.2 构造函数
    • 3.3 注解注入
  • 小结

一、如何理解IoC

1.1 Spring IOC 概述

  控制反转 IoC(Inversion of Control)是一种设计思想,DI (依赖注入)是实现 IoC 的一种方法,也有人认为 DI 只是 IoC 的另一种说法。没有 IoC 的程序中我们使用面向对象编程对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试,如下图所示:
在这里插入图片描述

  要理解IoC,需要弄清楚 「到底什么被反转了?如何反转的」?IoC 是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转移就是所谓反转。对于 Spring 而言,就是由 Spring 来控制对象的生命周期和对象之间的依赖关系。所有的类都会在 spring 容器中登记,告诉 spring 这是个什么东西,你需要什么东西,然后 spring 会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring 来控制,也就是说控制对象生存周期的不再是引用它的对象,而是 spring。
  IoC 还有另外一个名字——“依赖注入(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,即由容器动态地将某种依赖关系注入到组件之中。所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

1.2 IoC 是什么

  IoC 不是什么技术,而是一种设计思想,一个重要的面向对象编程的法则。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。我们来深入分析一下:

  • 谁控制谁,控制什么:传统 Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象。而 IoC 是有专门一个容器来创建这些对象,即由 Ioc 容器来控制对象的创建。关于谁控制谁?当然是 IoC 容器控制了对象;至于控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
  • 为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象。那为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转。至于哪些方面反转了?依赖对象的获取被反转了。

  在传统程序设计下,都是主动去创建相关对象然后再组合起来,我们需要用到那个类的对象,只需要 new 它就可以产生该类的对象了,然在在通过该对象调用它的属性和方法。如下图所示:
在这里插入图片描述

  类和类之间都是自行产生其他类的对象来进行使用,好处是使用简单,需要的时候 new 就行。但是缺点就有很多,用到哪些类都需要自身去创建,依赖度太高,不利于解耦,也有可能多个类都使用一个类的对象,但要产生多个对象,不能“共享”,冗余过多。当有了 IoC/DI 的容器后,在客户端类中不再主动去创建这些对象了,所有对象的产生都交给了容器来实现,当需要对象时,在通过容器获取它就行。如下图所示:
在这里插入图片描述

二、Ioc 配置的方式

  众所周知,Spring设计的两个大的要点:IOC和AOP。从框架的设计角度而言,更为重要的是简化开发,比如提供更为便捷的配置Bean的方式,直至0配置(即约定大于配置)。

2.1 xml 配置

  顾名思义,就是将bean的信息配置xml文件里,通过Spring加载文件为我们创建bean。这种方式出现很多早前的SSM项目中,将第三方类库或者一些配置工具类都以这种方式进行配置,主要原因是由于第三方类不支持Spring注解。使用这种配置的优点是可以使用于任何场景,结构清晰、通俗易懂;当然其缺点也比较明显,就是配置繁琐、不易维护,枯燥无味且扩展性差。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userService" class="org.dllwh.springframework.service.UserServiceImpl"><property name="userDao" ref="userDao"/></bean>
</beans>

2.2 Java 配置

  将类的创建交给我们配置的JavcConfig类来完成,Spring只负责维护和管理,采用纯Java创建方式。其本质上,就是把在XML上的配置声明转移到Java配置类中。这种方式适用于任何场景,配置方便,因为是纯Java代码,扩展性高,十分灵活。但由于是采用Java类的方式,声明不明显,如果大量配置,可读性比较差。
  实现这种配置,需要创建一个配置类, 添加 @Configuration 注解声明为配置类。然后创建方法,在方法上加上 @bean,该方法用于创建实例并返回,该实例创建后会交给spring管理,方法名建议与实例名相同(首字母小写)。

@Configuration
public class BeansConfig {@Bean("userDao")public UserDaoImpl userDao() {return new UserDaoImpl();}@Bean("userService")public UserServiceImpl userService() {UserServiceImpl userService = new UserServiceImpl();userService.setUserDao(userDao());return userService;}
}

2.3 注解配置

  通过在类上加注解的方式,来声明一个类交给 Spring 管理,Spring 会自动扫描带有 @Component@Controller@Service@Repository 这四个注解的类,然后帮我们创建并管理,前提是需要先配置Spring的注解扫描器。使用这种方式开发便捷,通俗易懂,方便维护。当然其具有局限性,对于一些第三方资源,无法添加注解,只能采用XML或JavaConfig的方式配置。如下所示:

@Service
public class UserServiceImpl {@Autowiredprivate UserDaoImpl userDao;public List<User> findUserList() {return userDao.findUserList();}
}

一些常用的注解,包括但不限于产生对象、引入依赖、设置配置等,如下表所示:

名称解释
@Component启动 Spring 后,会自动把它转成容器管理的 Bean
@Repository用于对DAO层注解,但是目前该功能与 @Component 相同
@Service用于对业务层注解,但是目前该功能与 @Component 相同
@Controller用于对控制层注解,但是目前该功能与 @Component 相同
@Scope作用域,等同于 XML 中的 scope 写法例如: @Component(“guanwei”) @Scope(“prototype”)
@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的 bean 才会按 照类型来装配注入
@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合 @Qualifier 一起使用
@Qualifier@Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了
@Configuration配置注解,标明当前类是一个配置类
@ComponentScan配置扫描那些包,一次可以扫描多个包
@Bean将方法的返回结果存放到 IoC 容器,就是手动产生对象并存放到 IoC 容器中
@Lazy设置当前类是否懒加载,配合产生对象注解使用

三、依赖注入的方式

常用的注入方式主要有三种:构造方法注入(Construct注入)、setter注入、基于注解的注入(接口注入)。

3.1 setter方式

  在XML配置方式中,property都是setter方式注入,比如下面的xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userService" class="org.dllwh.springframework.service.UserServiceImpl"><property name="userDao" ref="userDao"/></bean>
</beans>

  本质上包含两步:第一步,需要 new UserServiceImpl() 创建对象,所以需要默认构造函数;第二步,调用 setUserDao() 函数注入 userDao 的值,所以需要 setUserDao() 函数。所以对应的service类是这样的:

public class UserServiceImpl {private UserDaoImpl userDao;public UserServiceImpl() {}public List<User> findUserList() {return this.userDao.findUserList();}public void setUserDao(UserDaoImpl userDao) {this.userDao = userDao;}
}

  而在注解和Java配置方式下:

public class UserServiceImpl {private UserDaoImpl userDao;public List<User> findUserList() {return this.userDao.findUserList();}@Autowiredpublic void setUserDao(UserDaoImpl userDao) {this.userDao = userDao;}
}

  在 Spring 3.x 刚推出的时候,推荐使用注入的就是这种, 但是这种方式比较麻烦,所以在 Spring4 .x 版本中推荐构造函数注入。

3.2 构造函数

  在XML配置方式中,<constructor-arg> 是通过构造函数参数注入,比如下面的xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userService" class="tech.pdai.springframework.service.UserServiceImpl"><constructor-arg name="userDao" ref="userDao"/></bean>
</beans>

  本质上是new UserServiceImpl(userDao)创建对象,所以对应的service类是这样的:

public class UserServiceImpl {private final UserDaoImpl userDao;public UserServiceImpl(UserDaoImpl userDaoImpl) {this.userDao = userDaoImpl;}public List<User> findUserList() {return this.userDao.findUserList();}
}

  在注解和Java配置方式下

@Service
public class UserServiceImpl {private final UserDaoImpl userDao;@Autowiredpublic UserServiceImpl(final UserDaoImpl userDaoImpl) {this.userDao = userDaoImpl;}public List<User> findUserList() {return this.userDao.findUserList();}
}

3.3 注解注入

  以@Autowired(自动注入)注解注入为例,修饰符有三个属性:Constructor、byType、byName,默认按照byType注入。

属性说明
constructor通过构造方法进行自动注入,spring会匹配与构造方法参数类型一致的bean进行注入。如果有一个多参数的构造方法,
一个只有一个参数的构造方法,在容器中查找到多个匹配多参数构造方法的bean,那么spring会优先将bean注入到多参数的构造方法中。
byName被注入bean的id名必须与set方法后半截匹配,并且id名称的第一个单词首字母必须小写,这一点与手动set注入有点不同。
byType查找所有的set方法,将符合符合参数类型的bean注入。

比如:

@Service
public class UserServiceImpl {@Autowiredprivate UserDaoImpl userDao;public List<User> findUserList() {return userDao.findUserList();}
}

小结

  其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

在这里插入图片描述

  • https://www.pdai.tech/md/spring/spring-x-framework-ioc.html

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

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

相关文章

2024数学建模时间汇总与竞赛攻略

目录 2024数学建模汇总&#xff08;时间、报名费、获奖率、竞赛级别、是否可跨校&#xff09; 中国高校大数据挑战赛 “华数杯”国际大学生数学建模竞赛 美国大学生数学建模竞赛&#xff08;美赛&#xff09; 数学中国&#xff08;认证杯&#xff09;数学建模网络挑战赛 …

解决RuntimeError: cuDNN error: CUDNN_STATUS_EXECUTION_FAILED

下图说明在一瞬间我的GPU就被占满了 我的模型在训练过程中遇到了 CUDA 相关的错误&#xff0c;这是由于 GPU资源问题或内存不足导致的。这类错误有时候也可能是由于某些硬件兼容性问题或驱动程序问题引起的。 为了解决这个问题&#xff0c;可以尝试以下几个解决方案&#xff1a…

【Godot4.2】有序和无序列表函数库 - myList

概述 在打印输出或其他地方可能需要构建有序或无序列表。本质就是构造和维护一个纯文本数组。并用格式化文本形式&#xff0c;输出带序号或前缀字符的多行文本。 为此我专门设计了一个类myList&#xff0c;来完成这项任务。 代码 以下是myList类的完整代码&#xff1a; # …

模型剪枝-Network Slimming算法分析

代码见文末 论文地址&#xff1a;Learning Efficient Convolutional Networks through Network Slimming ICCV 2017 Open Access Repository 1.概述 由于边缘设备的限制&#xff0c;在模型的部署中经常受到模型大小、运行内存、计算量的限制。之前的方法要么只能解决其中一个…

spark实验求TOP值

实验1&#xff1a;求TOP值 已知存在两个文本文件&#xff0c;file1.txt和file2.txt&#xff0c;内容分别如下&#xff1a; file1.txt 1,1768,50,155 2,1218, 600,211 3,2239,788,242 4,3101,28,599 5,4899,290,129 6,3110,54,1201 7,4436,259,877 8,2369,7890,27 fil…

合泰杯(HT32F52352)RTC的应用(计时)--->掉电不丢失VBAT(代码已经实现附带源码)

摘要 在HT32F52352合泰单片机开发中&#xff0c;rtc在网上还是挺少人应用的&#xff0c;找了很久没什么资料&#xff0c;现在我根据手册和官方的代码进行配置理解。 RTC在嵌入式单片机中是一个很重要的应用资源。 记录事件时间戳&#xff1a;RTC可以记录事件发生的精确时间&…

STL——stackqueue

stack stack即为栈&#xff0c;先进后出是其特点 栈只有栈顶元素能被外界使用&#xff0c;故不存在遍历行为 栈中常用接口 构造函数 stack<T> stk; //默认构造方式 stack(const stack &stk); //拷贝构造 赋值操作 stack& operator(const stack &stk); …

动手学深度学习——softmax分类

1. 分类问题 回归与分类的区别&#xff1a; 回归可以用于预测多少的问题&#xff0c; 比如"预测房屋被售出价格"&#xff0c;它是个单值输出。softmax可以用来预测分类问题&#xff0c;例如"某个图片中是猫、鸡还是狗&#xff1f;"&#xff0c;这是一个多…

Apache POI 在java中处理excel

介绍: Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下&#xff0c;POI 都是用于操作 Excel 文件。 如何使用: 1.maven坐标引入 <depend…

安卓获取SHA

1&#xff1a;安卓通过签名key获取SHA 方式有两种&#xff0c; 1、电脑上来存在eclipse的用户或正在使用此开发工具的用户就简单了&#xff0c;直接利用eclipse 走打包流程&#xff0c;再打包的时候选择相应的签名&#xff0c;那么在当前面板的下面便会出现签名的相关信息。 2、…

iOS实现一个高性能的跑马灯

效果图 该跑马灯完全通过CATextLayer 实现&#xff0c;轻量级&#xff0c;并且通过 系统的位移动画实现滚动效果&#xff0c;避免了使用displaylink造成的性能瓶颈&#xff0c;使用系统动画&#xff0c;系统自动做了很多性能优化&#xff0c;实现更好的性能&#xff0c;并使用…

ChatGPT 网络安全秘籍(四)

原文&#xff1a;zh.annas-archive.org/md5/6b2705e0d6d24d8c113752f67b42d7d8 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第八章&#xff1a;事故响应 事故响应是任何网络安全策略的关键组成部分&#xff0c;涉及确定、分析和缓解安全漏洞或攻击。 及时和有效地…

LLM应用:让大模型prompt总结生成Mermaid流程图

生成内容、总结文章让大模型Mermaid流程图展示&#xff1a; mermaid 美人鱼, 是一个类似 markdown&#xff0c;用文本语法来描述文档图形(流程图、 时序图、甘特图)的工具&#xff0c;您可以在文档中嵌入一段 mermaid 文本来生成 SVG 形式的图形 Prompt 示例&#xff1a;用横向…

数智新重庆 | 推进信号升格 打造算力山城

2024年&#xff0c;是实现“十四五”规划目标任务的关键一年&#xff0c;高质量的5G网络、强大的AI能力作为新质生产力的重要组成部分&#xff0c;将有效赋能包括制造业在内的千行万业数字化化、智能化、绿色化转型升级&#xff0c;推动融合应用新业态、新模式蓬勃兴起&#xf…

【C语言】指针篇-精通库中的快速排序算法:巧妙掌握技巧(4/5)

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 一、回调函数二、快速排序(Qsort)2.1 Qsort参数部分介绍2.2 不…

1天搞定uniApp+Vue3+vite+Element UI或者Element Plus开发学习,使用vite构建管理项目,HBuilderX做为开发者工具

我们通常给小程序或者app开发后台时&#xff0c;不可避免的要用到可视化的数据管理后台&#xff0c;而vue和Element是我们目前比较主流的开发管理后台的主流搭配。所以今天石头哥就带大家来一起学习下vue3和Element plus的开发。 准备工作 1&#xff0c;下载HBuilderX 开发者…

数据库管理-第179期 分库分表vs分布式(20240430

数据库管理179期 2024-04-30 数据库管理-第179期 分库分表vs分布式&#xff08;20240430&#xff09;1 分库分表1.1 分库1.2 分表1.3 组合1.4 问题 2 分布式3 常见分布式数据库4 期望总结 数据库管理-第179期 分库分表vs分布式&#xff08;20240430&#xff09; 作者&#xff1…

应用监控(Prometheus + Grafana)

可用于应用监控的系统有很多&#xff0c;有的需要埋点(切面)、有的需要配置Agent(字节码增强)。现在使用另外一个监控系统 —— Grafana。 Grafana 监控面板 这套监控主要用到了 SpringBoot Actuator Prometheus Grafana 三个模块组合的起来使用的监控。非常轻量好扩展使用。…

iA Writer for Mac:简洁强大的写作软件

在追求高效写作的今天&#xff0c;iA Writer for Mac凭借其简洁而强大的功能&#xff0c;成为了许多作家、记者和学生的首选工具。这款专为Mac用户打造的写作软件&#xff0c;以其独特的设计理念和实用功能&#xff0c;助你轻松打造高质量的文章。 iA Writer for Mac v7.1.2中文…

【Jenkins】持续集成与交付 (四):修改Jenkins插件下载地址、汉化

🟣【Jenkins】持续集成与交付 (四):修改Jenkins插件下载地址、汉化 一、修改Jenkins插件下载地址二、汉化Jenkins三、关于Jenkins💖The Begin💖点点关注,收藏不迷路💖 一、修改Jenkins插件下载地址 由于Jenkins官方插件地址下载速度较慢,我们可以通过修改下载地址…