# my-spring
**Repository Path**: travelerly/my-spring
## Basic Information
- **Project Name**: my-spring
- **Description**: Spring 源码注释与图解
- **Primary Language**: Java
- **License**: GPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 14
- **Forks**: 6
- **Created**: 2021-03-12
- **Last Updated**: 2025-09-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
#
Spring Framework
---
> colin-source-test:spring 功能测试模块
>
> colin-mvc-test:mvc 功能测试模块
## Spring 基础
### Spring 如何工作
Spring 暴露给开发者的使用方式是,要么写一个 xml 文件、要么使用注解、要么利用磁盘文件、网络文件等,把需要的功能定义出来,这个信息最终会生成一个组件或者功能配置清单,Spring 会去读取并解析这些功能清单,这些信息就会决定 Spring 框架中的各种行为。
### Spring 整体架构流程
在 Spring 的底层把所有的资源(xml、注解、网络文件、磁盘文件等)都用 Resource 来表示,Resource 就是 Spring 内部对各种资源的一个抽象,Spring 使用 ResourceLoader(资源加载器)加载这些资源,交给 BeanDefinitionReader 来读取和解析,并存放到 Spring 工厂的 BeanDefinitionRegistry (Bean 定义信息注册中心)中,即 Spring 一启动,就将所有资源解析成 BeanDefinition 存入到 BeanDefinitionRegistry 中(实际是保存在一个 map 中,BeanDefinitionMap),然后 Spring 将这些 bean 的定义信息挨个创建成对象,并存入到 IOC 容器中,Spring 中使用各种池来存储对象,其中单例对象池用于保存所有的单例对象,在使用对象时,就去单例池中获取对象。
### Spring 核心组件
#### Bean 组件
Bean 组件定义在 Spring 的 `org.springframework.beans` 包下,解决了以下几个问题:
这个包下的所有类主要解决了三件事:
1. Bean 的定义
2. Bean 的解析
3. Bean 的创建
#### BeanFactory 组件
SpringBean 的创建是典型的工厂模式,它的顶级接口是 BeanFactory,其接口下的方法栈如下:
BeanFactory 的继承树:
BeanFactory 有三个子接口:
1. ListableBeanFactory
2. HierarchicalBeanFactory
3. AutowiredCapableBeanFactory
分三个子接口的目的是为了区分 Spring 内部对象处理和转化的数据限制,从继承树中可以看出最终的默认实现类是 DefaultListableBeanFactory,它实现了所有的接口。
#### BeanDefinition 组件
BeanDefinition 其保存了 Bean 的定义信息,例如这个 bean 指向的是哪个类、是否是单例、是否懒加载、依赖了那些 bean 等等。
#### Context 组件
Context 在 Spring 的 `org.springframework.context` 包下,是构建在 Core 和 Beans 模块基础之上,提供了一种类似于 JNDI 注册器的框架式的对象访问方法。Context 模块继承了 Beans 的特性,为 Spring 核心提供了大量扩展,添加了对国际化(例如资源绑定)、事件传播、资源加载和对 Context 的透明创建的支持。
#### ApplicationContext
ApplicationContext 是 Context 的顶级父类,其继承树如下:
##### ApplicationContext 与 BeanFactory
1. BeanFactory 是 Spring 框架中 IOC 容器的顶层接口,它只是用来定义一些基础功能、基础规范,而 ApplicationContext 是 BeanFactory 的一个子接口,所以 ApplicationContext 具备了 BeanFactory 提供的全部功能,就是一个 BeanFactory;
2. AnnotationConfigApplicationContext 组合了 DefaultListableBeanFactory,在 AnnotationConfigApplicationContext 执行构造方法时,先通过其父类 GenericApplicationContext 的构造方法创建了 DefaultListableBeanFactory,DefaultListableBeanFactory 及其父类初始化了以下组件:
- 用于保存 Bean 定义信息的集合、
- 用于保存实例的各种缓存池、
- Bean 定义信息的扫描器和读取器、
- 底层的后置处理器等,
然后 AnnotationConfigApplicationContext 再创建 BeanDefinition 的扫描器和读取器,并注册主配置类,最后调用 refresh() 方法刷新容器;
3. DefaultListableBeanFactory 是整个 bean 加载的核心部分,是 Spring 注册及加载 bean 的默认实现;
4. BeanFactory 定义工厂的创建和获取 Bean 的流程,其中包含有用于保存 Bean 定义信息的集合、保存实例的各种缓存池等,因此通常称为 IOC 的基础容器;
5. ==ApplicationContext 是建立在 BeanFactory 基础之上,是 IOC 容器的高级接口,比 BeanFactory 要拥有更多的功能,例如定义了 Bean 的各种增强处理的流程,提供了更多面向应用的功能,更易于创建实际应用,因此通常称为应用上下文;==
6. ApplicationContext 里面第一次要用到 bean,会使用工厂 BeanFactory 先来创建,创建好后保存在容器中;
7. ApplicationContext 中管理 bean 的能力是由 BeanFactory 提供支持的,即由 DefaultListableBeanFactory 提供支持的;
8. ==BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身,ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场景都可以直接使用 ApplicationContext,而非底层的 BeanFactory==
#### AOP:
1. AnnotationAspectJAutoProxyCreator 后置处理器,会在启动的时候分析所有标注了 @Aspect 注解的切面信息,将其封装成增强器链,并为目标对象创建代理放在容器中;
2. 执行期间代理对象会链式调用 AOP 切面定义的增强方法
#### 后置处理器
后置处理器是一种扩展机制,贯穿 Spring Bean 的生命周期。
Spring 提供了两种后置处理,分别为 BeanPostProcessor 和 BeanFactoryPostProcessor
BeanPostProcessor 是针对 Bean 级别的处理,可以针对某个具体的 Bean 进行后置处理,该接口提供了两个方法,在 Spring 容器实例化 bean 之后,分别是在 bean 的初始化方法之前和初始化方法之后执行。
- `postProcessorBeforeInitialization(Object bean,String beanName)`
- `postProcessorAfterInitialization(Object bean,String beanName)`
后置处理器默认会对整个 Spring 容器中的所有 bean 进行处理,如果需要处理某个具体的 bean,可以通过方法参数进行判断,
1. 参数一是每个 bean 实例,
2. 参数二是 bean 的 name 或者 id 属性的值。
> 处理是发生在 Spring 容器的实例化和依赖注入之后执行的
BeanFactoryPostProcessor 是针对整个 Bean 工厂级别的处理,可以在 bean 实例化之前,修改 bean 的定义信息,此接口只提供了一个方法
- postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
方法参数为 ConfigurableListableBeanFactory,而该接口中定义了一些方法,其中有一个方法可以根据 beanName 获得 bean 的 BeanDefinition,就可以对定义的属性进行修改
- BeanDefinition getBeanDefinition(String beanName)
> 调用 BeanFactoryPostProcessor 的方法时,bean 还没有被实例化,此时的 bean 刚刚被解析成 BeanDefinition 对象,所以可以通过 ConfigurableListableBeanFactory 的方法来获取 BeanDefinition,从而对 Bean 的定义信息进行处理增强。
#### 常用注解
1. @Configuration:表明当前类是一个配置类;
2. @PropertySource:引入外部属性配置文件
3. @Import:引入其它配置类
4. @Value:对变量赋值,可以直接赋值,也可以使用 `${}` 读取资源配置文件中的信息
5. @Bean:将当前方法返回的对象,直接加入到 IOC 容器中
#### Spring 的配置类
1. @Configuration、@Component、@ComponentScan、@Import、@ImportResource 等注解都可以注册配置类;
2. 标注了 @Configuration 注解的配置类称之为**"full"**配置类,FULL 配置类为传统配置类;
3. 标注了其它注解(非 @Configuration)的配置类称为**"lite"**配置类,Lite 配置类为普通 Bean 的配置类,例如注解 @Component、@Import 标注的类称为 Lite 配置类;
4. 对于**"full"**配置类,其会被 Cglib 所代理,在获取这个配置类对象时,实际上获取的是代理对象;
5. 而**"lite"**配置类则为普通的配置类对象,在获取这个配置类对象时,实际上获取的是原始的配置类对象
如果在配置类中定义两个 @Bean 方法,在其中一个 @Bean 方法中调用另一个 @Bean 方法
例如:car() 中调用 tank() 方法,当从容器中连续获取两次 Car 对象时,会因配置类的不同,而产生不同的结果:
- 如果是**"lite"**配置类,Tank 会被创建两次
- 如果是**"full"**配置类,Tank 只会被创建一次,因为配置类被 Cglib 代理了,方法被改写了
```java
//@Configuration
//@Component
public class ConfCglibConfig {
@Bean
public Car car(){
Car car = new Car();
car.setName("colin");
car.setTank(tank());
return car;
}
@Bean
public Tank tank(){
return new Tank();
}
}
```
#### Spring 的套路点:
1. AbstractBeanDefinition 如何给容器中注入了什么组件;
2. BeanFactory 初始化完成后,监控其中多了哪些后置处理器;
3. 分析后置处理器什么时候调用,做了什么功能。
以上所有的前提,是理解容器刷新 12 大步与 getBean() 流程,防止混乱;
1. 工厂后置处理器执行;
2. bean 后置处理器执行、bean 的生命周期(后置处理器 + InitializingBean)
### Spring架构原理图

### Bean 的生命周期:
Bean 生命周期的整个执行过程描述如下:
1. 根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean
2. 利用依赖注入完成 Bean 中所有属性值的配置注入
3. 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值
4. 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用
5. 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用
6. 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 方法对 Bean 进行增强操作
7. 如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法
8. 如果在配置文件中通过 init-method 属性指定了初始化方法,则 Spring 会调用该方法
9. 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始方法 postProcessAfterInitialization(),此时 Bean 已经可以被应用系统使用了
10. 如果在配置文件中指定了该 Bean 的作用范围是 scope=“singleton”,则将该 Bean 放入 IOC 容器中,将触发 Spring 对该 Bean 的生命周期管理,
11. 如果在配置文件中指定了该 Bean 的作用范围是 scope=“proptotype”,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean
12. 如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁,如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法
Spring 框架管理 Bean 对象的创建时,Bean 对象默认都是单例的,但也支持通过配置的方式来改变作用范围。
Bean 的增强过程:
1. BeanFactoryPostProcessor:在 BeanFactory 初始化前后拦截;
2. BeanPostProcessor:在所有组件创建对象及初始化前后拦截;
3. InitializingBean:组件单独实现它,可以在组件**赋值结束以后**调用初始化进行增强处理;
4. SmartInitializingBean:所有组件都创建好以后,每个组件再来 SmartInitializingBean
Bean:保存 BeanDefinition 信息→根据 BeanDefinition 信息创建对象→属性赋值→初始化;
Bean 的功能增强全都是由 BeanPostProcessor + InitializingBean (合起来)完成的
==使用建议:==
1. ==所有组件可能都会使用的功能,使用后置处理器 BeanPostProcessor 来实现;==
2. ==单个组件增强的功能,最好使用生命周期 InitializingBean 来实现==
组件新功能分析思路:
1. 组件的新功能一般都是由 Bean 的生命周期机制增强出来的;
2. 这个新功能加入了哪些组件,这些组件在生命周期期间做了什么
#### DI 依赖注入的实现方式
1. @Autowired(推荐使用)
@Autowired 是 Spring 提供的注解,需要导包:`org.springframework.beans.factory.annotation.Autowired`
@Autowires 采取的策略为按**照类型注入**
```java
public class TransferServiceImpl {
@Autowired
private AccountDao accountDao;
}
```
如上,装配时,到 IOC 容器中找到类型为 AccountDao 的类,然后将其注入到 TransferServiceImpl 中,但如果 AccountDao 类型存在多个 Bean 的时候,会造成无法选择具体注入哪一个 Bean 的情况,此时,需要配合着 @Qualifier 使用
2. @Autowired + @Qualifier
@Qualifier 会指定装配的对象
```java
public class TransferServiceImpl {
@Autowired
@Qualifier(name="jdbcAccountDaoImpl")
private AccountDao accountDao;
}
```
3. @Resource
@Resource 是由 J2EE 提供的,需要导包:` javax.annotation.Resource`,其在 JDK 11 中已经被移除,如需要使用,需要单独引入 jar 包
```xml
javax.annotation
javax.annotation-api
1.3.2
```
@Resource 默认是按照 beanName 自动注入的:
- 如果同时指定了 name 和 type,则从 Spring 上下文中找到唯一匹配的 bean 进行装配,找不到则抛出异常;
- 如果指定了 name,则从上下文中查找名称(id)匹配的 bean 进行装配,找不到则抛出异常;
- 如果指定了 type,则从上下文中找到类似匹配的唯一 bean 进行装配,找不到或是找到了多个,就会抛出异常;
- 如果既没有指定 name,也没有指定 type,则会自动按照 beanName 进行装配。
---
## Spring 容器初始化
### 容器刷新完整流程
Spring 容器启动时,先加载一些底层的后置处理器,例如 ConfigurationClassPostProcessor 配置类后置处理器,容器刷新时,执行工厂后置处理器,注册系统内所有配置类定义信息、AutowiredAnnotationBeanPostProcessor 自动装配功能后置处理器 ……,然后再将由构造传入的所有主配置类的定义信息注册进容器。然后开始刷新容器的步骤,即容器刷新十二大步。
1. **prepareRefresh()**:准备上下文环境,即是刷新预处理,与主流程关系不大,仅仅是保存了容器的启动时间、启动标志等;
2. **obtainFreshBeanFactory()**:初始化初级容器 BeanFactory,即**工厂的创建**,BeanFactory 的第一次创建(有 xml 的解析逻辑),获取当前准备好的空容器,返回在 this() 环节就准备(new)好的 BeanFactory,即返回 DefaultListableBeanFactory,其实现了 ConfigurableListableBeanFactory ;
3. **prepareBeanFactory(beanFactory)**:预准备工厂,给容器中注册了环境信息作为单实例 Bean,方便后续自动装配;beanPostProcessor 池中注册了一些后置处理器,例如处理监听功能的后置处理器 ApplicationListenerDetector、XXXAware(感知接口)功能的后置处理器 ApplicationContextAwareProcessor ;还设置了 忽略自动装配 和 允许自动装配 的接口;还设置了 bean 表达式解析器等;
4. **postProcessBeanFactory(beanFactory)**:留给子类的模板方法,允许子类继续对工厂执行一些处理(注册一些特殊的后置处理器);
5. **invokeBeanFactoryPostProcessors(beanFactory)**:工厂的增强或修改:**执行所有的 BeanFactory 后置处理器**,对工厂进行增强或修改(配置类会在这里解析),即执行 Spring 容器基本的后置处理。所有的 BeanDefinition 就已经准备就绪了。例如配置类的后置处理器 ConfigurationClassPostProcessor,会在此解析配置类,注册了所有标有 @Component、@ComponentScans、@ImportResource、@PropertySources、@Bean、@Import 等注解的 bean 的 BeanDefinition;
6. **registerBeanPostProcessors(beanFactory)**:**注册所有的 bean 的后置处理器**。例如:注册了创建 AOP 代理的入口 AnnotationAwareAspectJAutoProxyCreator、注册了与注解 @Autowired 相关的 AutowiredAnnotationBeanPostProcessor 等;
7. **initMessageSource()**:**初始化消息源 MessageResource**。观察容器中是否含有 MessageResource 的定义信息,如果没有就注册一个并放到单例池中;
8. **initApplicationEventMulticaster()**:**初始化事件多播器**(之后注册的监听器和发布事件都是基于该事件多播器执行的)。判断容器中是否有 id 为 applicationEventMulticaster 的定义信息,如果没有就注册一个事件多播器 ApplicationEventMulticaster 放到单例池中;
9. **onRefresh()**:留给子类继续增强处理逻辑,采用模板模式,用于在实例化 bean 之前,做一些其它初始化 bean 的工作;
10. **registerListeners()**:**初始化各种监听器**,关联 Spring 的事件监听机制。将容器中所有的监听器 ApplicationListener 保存进多播器集合中;
11. **finishBeanFactoryInitialization(beanFactory)**:**初始化所有非懒加载的单实例 bean**。详细参照 Bean 的初始化流程,再执行所有的后初始化操作,即 SmartInitializingSingleton.afterSingletonsInstantiated;
12. **finishRefresh()**:最后的一些清理、事件发送等处理,即初始化生命周期处理器,并发出相应的事件进行通知。

### 容器刷新之工厂的增强
`invokeBeanFactoryPostProcessors(beanFactory)`
工厂的增强或修改:执行所有的 BeanFactory 后置处理器,对工厂进行增强或修改(配置类会在这里解析),即执行 Spring 容器基本的后置处理。所有的 BeanDefinition 就已经准备就绪了。例如配置类的后置处理器 `ConfigurationClassPostProcessor`,会在此解析配置类,注册了所有标有 `@Component、@ComponentScans、@ImportResource、@PropertySources、@Bean、@Import` 等注解的 bean 的 BeanDefinition;
首先判断 beanFactory 是不是 BeanDefinitionRegistry 的实例,当然肯定是的,然后执行如下操作:
1. 定义了一个 Set,装载 BeanName,后面会根据这个 Set,来判断后置处理器是否被执行过了;
2. 定义了两个 List,一个是 `regularPostProcessors`,用来装载 `BeanFactoryPostProcessor`,一个是 registryProcessors 用来装载 BeanDefinitionRegistryPostProcessor,其中BeanDefinitionRegistryPostProcessor 扩展了 BeanFactoryPostProcessor。BeanDefinitionRegistryPostProcessor 有两个方法,一个是独有的 postProcessBeanDefinitionRegistry 方法,一个是父类的 postProcessBeanFactory 方法。
3. 循环传进来的 beanFactoryPostProcessors,上面已经解释过了,一般情况下,这里永远都是空的,只有手动 add beanFactoryPostProcessor,这里才会有数据。我们假设beanFactoryPostProcessors 有数据,进入循环,判断 postProcessor 是不是 BeanDefinitionRegistryPostProcessor,因为 BeanDefinitionRegistryPostProcessor 扩展了BeanFactoryPostProcessor,所以这里先要判断是不是 BeanDefinitionRegistryPostProcessor,是的话,执行 postProcessBeanDefinitionRegistry 方法,然后把对象装到registryProcessors 里面去,不是的话,就装到 regularPostProcessors。
4. 定义了一个临时变量:currentRegistryProcessors,用来装载 `BeanDefinitionRegistryPostProcessor`。
5. getBeanNamesForType,是根据类型查到 BeanNames,这里有一点需要注意,就是去哪里找,点开这个方法的话,就知道是循环 beanDefinitionNames 去找,这个方法以后也会经常看到。这里传了 BeanDefinitionRegistryPostProcessor.class,就是找到类型为 BeanDefinitionRegistryPostProcessor 的后置处理器,并且赋值给 postProcessorNames。一般情况下,只会找到一个,就是 org.springframework.context.annotation.internalConfigurationAnnotationProcessor,也就是 ConfigurationAnnotationProcessor。这个后置处理器在上一节中已经说明过了,十分重要。这里有一个问题,为什么我自己写了个类,实现了 BeanDefinitionRegistryPostProcessor 接口,也打上了 @Component 注解,但是这里没有获得,因为直到这一步,Spring 还没有完成扫描,扫描是在 ConfigurationClassPostProcessor 类中完成的,也就是下面第一个 invokeBeanDefinitionRegistryPostProcessors 方法。
6. 循环 postProcessorNames,其实也就是 org.springframework.context.annotation.internalConfigurationAnnotationProcessor,判断此后置处理器是否实现了 PriorityOrdered 接口(ConfigurationAnnotationProcessor 也实现了 PriorityOrdered 接口),如果实现了,把它添加到 currentRegistryProcessors 这个临时变量中,再放入 processedBeans,代表这个后置处理已经被处理过了。当然现在还没有处理,但是马上就要处理了。。。
7. 进行排序,PriorityOrdered 是一个排序接口,如果实现了它,就说明此后置处理器是有顺序的,所以需要排序。当然目前这里只有一个后置处理器,就是 ConfigurationClassPostProcessor。
8. 把 currentRegistryProcessors 合并到 registryProcessors,为什么需要合并?因为一开始 spring 只会执行 BeanDefinitionRegistryPostProcessor 独有的方法,而不会执行BeanDefinitionRegistryPostProcessor 父类的方法,即 BeanFactoryProcessor 接口中的方法,所以需要把这些后置处理器放入一个集合中,后续统一执行 BeanFactoryProcessor 接口中的方法。当然目前这里只有一个后置处理器,就是 ConfigurationClassPostProcessor。
9. 可以理解为执行 currentRegistryProcessors 中的 ConfigurationClassPostProcessor 中的 postProcessBeanDefinitionRegistry 方法,这就是 Spring 设计思想的体现了,在这里体现的就是其中的**热插拔**,插件化开发的思想。Spring 中很多东西都是交给插件去处理的,这个后置处理器就相当于一个插件,如果不想用了,直接不添加就是了。这个方法特别重要,我们后面会详细说来。
10. 清空 currentRegistryProcessors,因为 currentRegistryProcessors 是一个临时变量,已经完成了目前的使命,所以需要清空,当然后面还会用到。
11. 再次根据 BeanDefinitionRegistryPostProcessor 获得 BeanName,然后进行循环,看这个后置处理器是否被执行过了,如果没有被执行过,也实现了 Ordered 接口的话,把此后置处理器推送到 currentRegistryProcessors 和 processedBeans 中。
> 这里就可以获得我们定义的,并且打上 @Component 注解的后置处理器了,因为 Spring 已经完成了扫描,但是这里需要注意的是,由于 ConfigurationClassPostProcessor 在上面已经被执行过了,所以虽然可以通过 getBeanNamesForType 获得,但是并不会加入到 currentRegistryProcessors 和 processedBeans。
12. 处理排序。
13. 合并 Processors,合并的理由和上面是一样的。
14. 执行我们自定义的 BeanDefinitionRegistryPostProcessor。
15. 清空临时变量。
16. 在上面的方法中,仅仅是执行了实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor,这里是执行没有实现 Ordered 接口的 BeanDefinitionRegistryPostProcessor。
17. 上面的代码是执行子类独有的方法,这里需要再把父类的方法也执行一次。
18. 执行 regularPostProcessors 中的后置处理器的方法,需要注意的是,在一般情况下,regularPostProcessors 是不会有数据的,只有在外面手动添加 BeanFactoryPostProcessor,才会有数据。
19. 查找实现了 BeanFactoryPostProcessor 的后置处理器,并且执行后置处理器中的方法。和上面的逻辑差不多,不再详细说明。
这就是这个方法中做的主要的事情了,可以说是比较复杂的。但是逻辑还是比较清晰的,在第9步的时候,我说有一个方法会详细说来,现在就让我们好好看看这个方法究竟做了什么吧。
1. 获得所有的 BeanName,放入 candidateNames 数组。
2. 循环 candidateNames 数组,根据 beanName 获得 BeanDefinition,判断此 BeanDefinition 是否已经被处理过了。
3. 判断是否是配置类,如果是的话。加入到 configCandidates 数组,在判断的时候,还会标记配置类属于Full配置类,还是 Lite 配置类,这里会引发一连串的知识盲点:
1. 当我们注册配置类的时候,可以不加 @Configuration 注解,直接使用 @Component、@ComponentScan、@Import、@ImportResource 等注解,Spring 把这种配置类称之为 **Lite** 配置类, 如果加了 @Configuration 注解,就称之为 **Full** 配置类。
2. 如果我们注册了 **Lite** 配置类,我们 getBean 这个配置类,会发现它就是原本的那个配置类,如果我们注册了 **Full** 配置类,我们 getBean 这个配置类,会发现它已经不是原本那个配置类了,而是已经被 cgilb 代理的类了。
3. 写一个 A 类,其中有一个构造方法,打印出“你好”,再写一个配置类,里面有两个被 @Bean 注解的方法,其中一个方法 new 了 A 类,并且返回 A 的对象,把此方法称之为 getA,第二个方法又调用了 getA 方法,如果配置类是 **Lite** 配置类,会发现打印了两次“你好”,也就是说 A 类被 new 了两次,如果配置类是 **Full** 配置类,会发现只打印了一次“你好”,也就是说 A 类只被 new 了一次,因为这个类被 cgilb 代理了,方法已经被改写。
4. 如果没有配置类直接返回。
5. 处理排序。
6. 解析配置类,可能是 **Full** 配置类,也有可能是 **Lite** 配置类,这个小方法是此方法的核心,稍后具体说明。
7. 在第 6 步的时候,只是注册了部分 Bean,像 @Import、@Bean 等,是没有被注册的,这里统一对这些进行注册。
---
## Spring 事件原理
### Spring 事件的使用
Spring 事件体系包括三个组件:事件、事件监听器、事件多播器
### Spring 内置事件
内置事件由系统内部进行发布,只需注入监听器
| Event | 说明 |
| --------------------- | ------------------------------------------------------------ |
| ContextRefreshedEvent | 当容器被实例化或 refreshed 时发布。如调用 refresh() 方法,此处的实例化是指所有的 bean 都已被加载,后置处理器都被激活,所有单例 bean 都已被实例化,所有的容器对象都已准备好可使用。如果容器支持热重载,则 refresh 可以被触发多次(XmlWebApplicatonContext 支持热刷新,而GenericApplicationContext 则不支持) |
| ContextStartedEvent | 当容器启动时发布,即调用 start() 方法,已启用意味着所有的 Lifecycle bean 都已显式接收到了 start 信号 |
| ContextStoppedEvent | 当容器停止时发布,即调用 stop() 方法,即所有的 Lifecycle bean 都已显式接收到了 stop 信号,关闭的容器可以通过 start() 方法重启 |
| ContextClosedEvent | 当容器关闭时发布,即调用 close 方法,关闭意味着所有的单例 bean 都已被销毁。关闭的容器不能被重启或 refresh |
| RequestHandledEvent | 这只在使用 spring 的 DispatcherServlet 时有效,当一个请求被处理完成时发布 |
### Spring 自定义事件
1. 自定义组件装配 ApplicationContext 或者 ApplicationEventMulticaster,可以派发事件;
2. 自定义组件实现 ApplicationListener 或者使用注解 @EventListener 标注在方法上,可以接收事件;
3. publish 的 Object 对象会被认为是自定义事件,也可以定义事件(通过实现 ApplicationEvent)。

### Spring 事件原理
原理:观察者模式
spring 事件监听有三个部分组成
- ApplicationEvent 事件:赋值对应相应监听器,事件源发生某事件是特定事件监听器触发的原因
- ApplicationListener 监听器:对应于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应逻辑
- ApplicationEventMulticaster 事件多播器:对应于观察者模式中的被观察者/主题,负责通知观察者,对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器之间的映射关系,并在事件发生时,负责通知相关的监听器。
Spring 事件机制是观察者模式的一种实现,除了事件发布者和事件监听者两个角色之外,还有一个事件多播器 EventMulticaster 的角色负责把事件转发给监听者。即发布者是将事件发送给了事件多播器 EventMulticaster,而后由事件多播器中注册着所有的监听器 Listener,然后根据事件类型决定转发给那个 Listener。
工作流程如下:

---
## Bean 的生命周期
### Bean的初始化流程

### Bean生命周期

#### 工厂 Bean 创建对象的步骤:
1. 定义工厂 bean:实现 FactoryBean 接口,并指定 bean 的类型(例如 Hello),并重写方法 getObject() 和 getObjectType(),getObjectType() 方法的返回值与指定的类型一致,getObject() 方法中定义指定类型的 bean 的创建方法,例如 new Hello()。
2. 从容器中获取指定类型的 bean 实例对象,例如获取 Hello 的实例对象:
1. 获取可以匹配指定类型的组件名称,遍历容器中所有组件进行筛选
- 若当前遍历到的组件是工厂 bean,且工厂 bean 中的 getObjectType() 方法的返回值与指定类型相同,则返回此工厂组件名称
- 若当前组件是普通 bean,则直接返回该组件的名称
2. 根据组件名称来获取组件实例对象
- 若组件是工厂 bean,则调用工厂 bean 的 getObject() 方法,获取指定类型的实例对象;
- 若组件是普通 bean,则调用 spring 获取对象
### 循环引用

### AOP 的循环引用

#### 三级缓存
1. singletonObjects:一级缓存,即 spring 的 ioc 容器,用于存放完整的 bean 实例(已经完成属性赋值和初始化的实例对象)
2. earlySingletonObjects:二级缓存,存放半成品的 bean 实例(尚未被属性赋值和初始化)
- 如果 bean 不被 AOP 切面代理,则其保存的是(未属性赋值的半成品的)bean 实例
- 如果 bean 被 AOP 切面代理,则其保存的是代理的 bean 实例--beanProxy,其目标 bean 还是半成品的。
3. singletonObjects:三级缓存,存放的是 ObjectFactory,是一个函数式接口,当执行 objectFactory#getObject() 方法时,最终会调用 getEarlyBeanReference(beanName, mbd, bean),来获取 bean 的早期引用
- 如果 bean 被 AOP 代理,则其会返回 bean 的代理对象
- 如果 bean 没有被 AOP 代理,则其会返回原 bean 实例对象
#### 循环引用与三级缓存
只使用一级缓存和三级缓存就可以解决(非 AOP 代理类的)循环依赖:一级缓存存放完整 bean、三级缓存存放提前暴露出来的对象工厂(用于创建 bean 的 lambda 表达式)
对于被 AOP 代理的 bean 的循环依赖需使用三级缓存解决:因为三级缓存中的 ObjectFactory 每执行一次就会创建一个对象,此时需要借助另外一个缓存来存放 objectFactory#getObject() 创建的对象,即使用二级缓存来存储其创建的对象,所以,对于被 AOP 代理的 bean 的循环依赖需使用三级缓存解决。
#### 二级缓存存在的问题
1. 生成 A 的实例,然后放入缓存中,A 需要注入属性 B;
2. 生成 B 的实例,B 需要注入属性 A,从缓存中获取 A 并注入到 B 中,并完成 B 的初始化;
3. 将完成初始化后的 B 注入到 A 中,再完成 A 的初始化;
4. 由于 A 是 AOP 的目标类,在其初始化后,后置处理器(AbstractAutoProxyCreator)介入,为 A 生成动态代理类。
A 的最终产物为 A 的代理类,而 B 中注入的属性 A 为原始类,与代理类不是同一个对象,违背了 Spring 的单例原则
#### 为什么要使用二级缓存 earlySingletonObjects?
1. 如果不涉及 AOP 代理,二级缓存就会显得多此一举,但如果使用了 AOP 代理,那么二级缓存就发挥作用了。bean 的 AOP 动态代理对象的创建时在 bean 的初始化之后实现的,但是循环依赖的 bean 就无法等到解决完循环依赖后再创建其代理对象了,因为这个时候需要属性注入,所以如果循环依赖的 bean 被 AOP 代理了,则需要提前创建出代理对象,然后放入到二级缓存中;
2. 三级缓存中存放的是 ObjectFactory 对象工厂,当执行 objectFactory#getObject() 回调时,会调用 getEarlyBeanReference() 方法。获取 bean 的早期引用,每次调用都会产生一个新的代理对象,这有悖于 Spring 的单例设计理念
3. 所以使用二级缓存来缓存 bean 的早期引用,后续步骤可以从二级缓存中获取,就解决了因每次都调用都产生新代理对象的这个问题了,从而保证这个 bean 始终都只有这一个代理对象。
#### 三级缓存解决问题
三级缓存中存储的是 singletonFactories,是某个 beanName 及其对应的 objectFactory,这个 ObjectFactory 其实就是生成这个 Bean 的工厂。
是在给 B 的属性赋值时,需要注入 A,则从三级缓存中取出 A 的缓存数据,即能够生产 A 的 objectFactory,最终回调 getEarlyBeanReference() 方法完成代理对象的创建。
getEarlyBeanReference() 方法具体作用:
1. 根据 beanName 将它对应的实例化后且未初始化的 Bean 存入到 Map