## 第六章:Spring IoC依赖注入(Dependency Injection)
## 依赖注入的模式和类型
- 手动模式 - 配置或者编程的方式,提前安排注入规则
- XML 资源配置元信息
- Java 注解配置元信息
- API 配置元信息
- 自动模式 - 实现方提供依赖自动关联的方式,按照內建的注入规则
- Autowiring(自动绑定)
## 依赖注入类型
| 依赖注入类型 | 配置元数据举例 |
| ------------ | -------------------------------------------------- |
| Setter 方法 | `` |
| 构造器 | `` |
| 字段 | `@Autowired User user;` |
| 方法 | `@Autowired public void user(User user) { ... }` |
| 接口回调 | `class MyBean implements BeanFactoryAware { ... }` |
## 自动绑定(Autowiring)模式,Autowiring modes
参考枚举:`org.springframework.beans.factory.annotation.Autowire`
| 模式 | 说明 |
| ----------- | ------------------------------------------------------------ |
| no | 默认值,未激活 Autowiring,需要手动指定依赖注入对象。 |
| byName | 根据被注入属性的名称作为 Bean 名称进行依赖查找,并将对象设置到该属性。 |
| byType | 根据被注入属性的类型作为依赖类型进行查找,并将对象设置到该属性。 |
| constructor | 特殊 byType 类型,用于构造器参数。 |
## setter方法注入
* 实现方法
* 手动模式
* XML资源配置元信息
* JAVA注解配置元信息
* API配置元信息
* 自动模式
* byName
* byType
## 构造器注入
* 实现方法
* 手动模式
* XML资源配置元信息
* JAVA注解配置元信息
* API配置元信息
* 自动模式
* constructor -- 特殊的bytype
## 字段注入
* 实现方法
* 手动方式
* JAVA注解配置元信息
* @Autowired
* @Resource
* @inject (可选)
## 方法注入
* 实现方法
* 手动模式
* JAVA注解配置元信息
* @Autowired
* @Resource
* @inject (可选)
* Bean
## Aware 系列接口回调
| 內建接口 | 说明 |
| ------------------------------ | -------------------------------------------------------- |
| BeanFactoryAware | 获取 IoC 容器 - BeanFactory |
| ApplicationContextAware | 获取 Spring 应用上下文 - ApplicationContext 对象 |
| EnvironmentAware | 获取 Environment 对象 |
| ResourceLoaderAware | 获取资源加载器 对象 - ResourceLoader |
| BeanClassLoaderAware | 获取加载当前 Bean Class 的 ClassLoader |
| BeanNameAware | 获取当前 Bean 的名称 |
| MessageSourceAware | 获取 MessageSource 对象,用于 Spring 国际化 |
| ApplicationEventPublisherAware | 获取 ApplicationEventPublishAware 对象,用于 Spring 事件 |
| EmbeddedValueResolverAware | 获取 StringValueResolver 对象,用于占位符处理 |
## 依赖注入类型选择
- 低依赖:构造器注入
- 多依赖:Setter 方法注入 --- 注入时机没有顺序
- 便利性:字段注入
- 声明类:方法注入 --- 不建议使用,建议配置@Bean使用
## 各种类型注入
- 基础类型
- 原生类型(Primitive):boolean、byte、char、short、int、float、long、double
- 标量类型(Scalar):Number、Character、Boolean、Enum、Locale、Charset、Currency、Properties、UUID
- 常规类型(General):Object、String、TimeZone、Calendar、Optional 等
- Spring 类型:Resource、InputSource、Formatter 等
- 集合类型
- 数组类型(Array):原生类型、标量类型、常规类型、Spring 类型
- 集合类型(Collection)
- Collection:List、Set(SortedSet、NavigableSet、EnumSet)
- Map:Properties
- 限定注入
- 使用注解 @Qualifier 限定
- 通过 Bean 名称限定
- 通过分组限定
- 基于注解 @Qualifier 扩展限定
- 自定义注解,如 Spring Cloud @LoadBalanced
- 延迟依赖注入
- 使用API ObjectFactory 延迟注入
- 单一类型
- 集合类型
- 使用API ObjectProvider 延迟注入(推荐)
- 单一类型
- 集合类型
- 使用 API ObjectFactory 延迟注入
- 单一类型
- 集合类型
- 使用 API ObjectProvider 延迟注入(推荐)
- 单一类型
- 集合类型
## 依赖处理过程
- 入口 - `DefaultListableBeanFactory#resolveDependency`
- 依赖描述符 - Dependency Descriptor
- 自定绑定候选对象处理器 - AutowireCandidateResolver
## @autowired注入过程
* 元信息解析
* 依赖查找(依赖处理)
* 依赖注入(字段,方法)
@Autowired、@Inject 注入,参考 `AutowiredAnnotationBeanPostProcessor`
## Java通用注解注入原理:
- `CommonAnnotationBeanPostProcessor`
- 注入注解
- javax.xml.ws.WebServiceRef
- javax.ejb.EJB
- javax.annotation.Resource
- 生命周期注解
- javax.annotation.PostConstruct
- javax.annotation.PreDestroy
## 自定义依赖注入注解
- 基于 `AutowiredAnnotationBeanPostProcessor` 实现
- 自定义实现
- 生命周期处理
- InstantiationAwareBeanPostProcessor
- MergedBeanDefinitionPostProcessor
- 元数据
- InjectedElement
- InjectionMetadata
- `org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor`
- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
- `@Autowired`
- `@Value`
- `@Inject`
- org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
- `@PostConstruct`
- `@PreDestroy`
初始化 Bean 时,`AutowiredAnnotationBeanPostProcessor` 先解析 Bean 中的依赖(`@Autowire`,`@Value`),然后 `CommonAnnotationBeanPostProcessor` 调用初始化方法 `@@PostConstruct`
将 `@Bean` 方法设置为 `static` ,可以让 Bean 提前初始化。
- 依赖查找:`ApplicationContext#getBean`
- 依赖处理过程:`org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency`
# 面试题精选
1、有多少种依赖注入的方式?
![image-20221009100805500](assets/image-20221009100805500.png)
2、偏好构造器注入还是setter注入?
![image-20221009100904481](assets/image-20221009100904481.png)
3、spring依赖注入的来源有哪些?
![image-20221009100952662](assets/image-20221009100952662.png)