IOC和DI概述
IoC(Inversion of Control)控制反转,包含了两个方面:一、控制。二、反转
我们可以简单认为:
- 控制指的是:当前对象对内部成员的控制权
- 反转指的是:这种控制权不由当前对象管理了,由其他(类,第三方容器)来管理
IOC不够开门见山,于是Martin Fowler提出了DI(dependency injection)来替代IoC,即让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入,以移除调用类对某一接口实现类的依赖
之前是在对象内部 new 创建其他对象,然后使用,而现在 Spring 中有一个容器可以在创建管理这些对象,并且将对象依赖的其他对象注入到这个对象中,这些对象的创建、销毁都由 Spring 进行管理 相比以前来说,不再由自己控制其他对象的生命周期,这个过程就叫做控制反转。而负责统一管理这些类的容器就叫做 IoC 容器
- IoC(思想,设计模式)主要的实现方式有两种:依赖查找,依赖注入
- DI(Dependency Injection)依赖注入是一种更可取的方式(实现的方式)
依赖注入的三种方式
1. 构造器注入
将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入
优点:
对象初始化完成后便可获得可使用的对象
缺点:\
- 当需要注入的对象很多时,构造器参数列表将会很长;\
- 不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函数,麻烦
2. setter方法注入
IoC Service Provider通过调用成员变量提供的setter函数将被依赖对象注入给依赖类
优点:
灵活。可以选择性地注入需要的对象。
缺点:
依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用
3. 接口注入
依赖类必须要实现指定的接口,然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参数就是要注入的对象
接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可
缺点:
侵入性太强,不建议使用
Spring IOC的好处
- 资源集中管理,实现资源的可配置和易管理
- 降低了使用资源双方的依赖程度,也就是我们说的耦合度
- 不用自己组装,拿来就。
- 享受单例的好处,效率高,不浪费空间
- 便于单元测试,方便切换mock组件
- 便于进行AOP操作,对于使用者是透明的
Spring IOC实现流程图
- 创建baenFactory容器
- 加载配置文件,解析bean定义信息,包装成BeanDifiniton
- 执行BeanFactoryPostProcessor
准备工作:准备BeanPostProcessor,监听器等
- 实例化操作
- 初始化操作
- 获取对象
ApplicationContext.refresh()方法
Spring IOC的三种注入方式:属性注入,构造器注入,自动装配
目前最常用的是自动装配:
在类前面加注解:@Component,在需要注入的类里面加注解:@Autowired,这样xml里面的自动扫描就会扫描到这些加了注解的类和属性,在实例化bean的时候,Spring容器会把加了@Component的类实例化;在实际运行时,会给加了@Autowired的属性注入对应的实例
Spring中的自动装配有哪些限制?
- 如果使用了构造器注入或者setter注入,那么将覆盖自动装配的依赖关系
- 基本数据类型的值、字符串字面量、类字面量无法使用自动装配来注入
- 有先考虑使用显式的装配来进行更精确的依赖注入而不是使用自动装配
和自动装配相关的注解
- @Required:该依赖关系必须装配(手动或自动装配),否则将抛出BeanInitializationException异常
- @Autowired:自动装配,默认按类型进行自动装配
- @Qualifier:如果按类型自动装配时有不止一个匹配的类型,那么可以使用该注解指定名字来消除歧义