目录
IoC——控制反转,是 Spring 框架的核心概念之一,是一种设计原则和编程模式,用于实现松耦合和可测试的应用程序
控制反转:对象的生命周期不是由程序员来控制,而是由 Spring 来控制(传统的编程模式中,对象之间的创建、组装和管理都是由开发人员手动完成,在 IoC 模式下,这些责任被委托给一个容器来管理)
IoC 最大的优点:实现解耦合(松耦合)
在传统开发中:比如构建一辆汽车
构建汽车对象,然后依赖车身建立车身对象,车身依赖底盘建立底盘对象,底盘依赖轮胎建立轮胎对象,如果想要改变轮胎尺寸需要在整个调用链上所有代码都需要修改,本质需要改动的越少越好
IoC程序开发:
改进之后:不再是上级对象创建并控制下级对象,而下级对象注入当前对象即使下级类发?任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想,实现了解耦合
IoC 容器主要通过两种方式实现控制反转:
DI 的实现原理是通过反射机制实现的。通过反射给成员变量赋值,这里的成员变量就是我们所说的依赖。比如TestController当中有个TestService对象,他需要依赖TestService对象当中的方法,那么TestService就是TestController的依赖。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
这里就考验到了通过反射我们有几种方式可以给TestService赋值,一共有如下三种:
1??直接给属性赋值
优点:实现简单、使用简单,只需要给变量上添加一个注解(@Autowired),就可以在不 new 对象的情况下,直接获得注入的对象了(这就是 DI 的功能和魅力所在)
缺点:无法注入 final 修饰的变量;只适用于 IoC 容器;违背单一设计原则
2??通过set方法给变量赋值
优点:通常 Setter 只 Set 一个属性,所以 Setter 注入更符合单一设计原则
缺点:无法注入 final 修饰的变量;setter 注入的对象可以被修改(setter 本来就是一个方法,有可能被多次调用和修改)
3??通过构造方法给变量赋值:如果当前的类中只有一个构造方法,那么 @Autowired 也可以省略
Spring 官方从 4.x 之后推荐的注入方式
优点:可以注入 final 修饰的变量;注入的对象是不会被修改(因为构造方法只会加载一次);构造方法注入可以保证注入对象完全初始化;构造方法注入通用性更好
缺点:写法比属性注入复杂、使用构造方法注入,无法解决循环依赖的问题
?当使用 @Autowired 注释时,Spring 容器会自动查找与该类型匹配的 bean,并将其注入到该字段中。如果有多个匹配的 bean,则可以使用 @Qualifier 注释来指定要注入的 bean 的名称。
当使用 @Value 注释时,Spring 容器会将属性值注入到该字段中。属性值可以从配置文件中读取,也可以是硬编码的值。
4??另外一种注入关键字@Resource
1??出身不同:@Resource 来自于JDK;@Autowired 来自于 Spring 框架
2??支持的参数不同:@Resource 支持很多参数设;@Autowired 只支持一个参数设置(@Qualifier)
3??使用区别:@Resource 不支持构造方法注入;而 @Autowired 支持构造方法注入
4??idea 兼容性支持不同:使用 @Autowired 在 idea 专业版可能会报错;@Resource 不存在误报的问题
@Autowired来自于 spring,spring 框架是在程序执行之后再执行,不能检测到当前类是否注入(注入是的到 spring 当中)
@Resource:java代码是在程序执行之前执行的,能检测到已经注入
例如:我在开直播,有人先进来可以听到我之前讲的知识,有人后来就听不到我之前讲的知识,但是对于这个知识我已经讲过了,这个知识点是存在的。
IoC 和 DI 都是 Spring 框架中的核心概念,它们的区别在于:
简单来说,它们的关系是:
比如说我今天吃?顿美餐,那么“美餐”是目标(是 IoC),但最后我是吃火锅还是烧烤?这就是具体的实现,就是DI
例如在 Spring 框架中:
- IoC 体现为 Spring 容器承担了对象创建及依赖关系管理的控制权。
- DI 体现为 Spring 容器通过构造方法注入、Setter 方法注入等方式,将依赖对象注入到需要依赖的对象中。
所以综上,IoC 和 DI 之间的关系可以这样理解:
- IoC 是理论,DI 是实践。
- IoC 是思想,DI 是手段。
- IoC 是整体,DI 是部分。