对于普通的Java
对象,当new
的时候创建对象,当它没有任何引用的时候被垃圾回收机制回收。而由Spring IoC
容器托管的对象,它们的生命周期完全由容器控制。
普通Java对象和Spring所管理的Bean的区别
- 首先要知道的是普通
Java
对象和Spring
所管理的Bean
实例化的过程是有些区别的在普通Java环境下创建对象简要的步骤可以分为:
- java源码被编译为被编译为
class
文件 - 等到类需要被初始化时(比如说
new
、反射
等) -
class
文件被虚拟机通过类加载器加载到JVM
- 初始化对象供我们使用
- 简单来说,可以理解为它是用Class对象作为「模板」进而创建出具体的实例
而Spring
所管理的Bean
不同的是,除了Class
对象之外,还会使用BeanDefinition
的实例来描述对象的信息 - 比如说: 我们可以在
Spring
所管理的Bean有一系列的描述:@Scope、@Lazy、@DependsOn 等等 - 可以理解为:Class只描述了类的信息,而BeanDefinition描述了对象的信息
BeanDefinition定义SpringBean的类信息
-
Spring
在启动的时候需要「扫描」在XML / 注解 / JavaConfig 中需要被Spring管理的Bean
信息 - 随后,会将这些信息封装成
BeanDefinition
,最后会把这些信息放到一个beanDefinitionMap
中
扫描 -> 收集至BeandefinitionMap
- 接着会遍历这个
beanDefinitionMap
,执行BeanFactoryPostProcessor
这个Bean工厂后置处理器的逻辑
这里我们也可以自定义BeanFactoryPostProcessor
来对我们定义好的Bean元数据进行获取或者修改
BeanFactoryPostProcessor处理器执行完了以后,就到了实例化对象了,下面这张图是Bean的整个生命周期:
1、实例化Bean
- 在Spring里面是通过
反射机制
来实现的,一般情况下会通过反射选择合适的构造器来把对象实例化,这里把对象实例化,只是把对象给创建出来,而对象具体的属性是还没注入的。
2、注入对象属性(populateBean)
- 实例化后的对象被封装在
BeanWrapper
对象中。紧接着,Spring
根据BeanDefinition
中的信息进行依赖注入。并且通过BeanWrapper
提供的设置属性的接口完成依赖注入。 - 提示:在这一步涉及到了循环依赖问题(
三级缓存
:Bean对象在实例化后会放入第三级缓存singletonFactories
(key: beanName,value: objectFactory)
相关属性注入完之后,往下接着就是初始化的工作了
3、检查Aware相关接口并设置相关依赖
- 首先判断该Bean是否实现了Aware相关的接口,如果存在则填充相关的资源
比如我希望通过代码程序的方式去获取指定的Spring Bean
我们这边会抽取成一个工具类,去实现ApplicationContextAware
接口,来获取ApplicationContext
对象进而获取Spring Bean
Aware相关的接口处理完之后,就会到BeanPostProcessor了
4、BeanPostProcessor(后置处理器)
- BeanPostProcessor这个接口有两个方法,一个是
before
,一个是after
- 所以,执行完Aware相关的接口就会执行BeanPostProcessor里面的的
before
方法
BeanPostProcessor相关方法before执行完了后就会执行 init 相关的方法
5、InitializingBean与init-method
- init 相关方法:
@PostConstruct
、实现了InitializingBean
接口、定义的init-method
方法 - InitializingBean接口里只有一个方法
afterPropertiesSet()
- 这一阶段也可以在
bean
正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会
把当前bean
对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。 - 当时我还去官网去看他们的被调用执行顺序分别是:@PostConstruct、实现了InitializingBean接口以及init-method方法
init方法执行完之后,就会执行BeanPostProcessor的after方法也就是后置处理器
6、BeanPostProcessor(后置处理器)
- 这个BeanPostProcessor后置处理器是
AOP
实现的关键(关键子类AnnotationAwareAspectJAutoProxyCreator
) - 当前正在初始化的bean对象会被传递进来,我们就可以对这个
bean
作任何处理。Spring
的AOP
就是在这里实现的
7、基本重要的流程已经走完了,我们就可以获取到对象去使用了
8、最后就是销毁,销毁的时候就看有没有配置相关的destroy方法,执行就完事了
我稍微总结一下今天的内容吧
- 首先是Spring Bean的生命周期过程,
Spring
使用BeanDefinition
来装载着我们给Bean定义的元数据 - 实例化Bean的时候实际上就是遍历
BeanDefinitionMap
- Spring的
Bean
实例化和属性赋值是分开两步来做的 - 在Spring Bean的生命周期,Spring预留了很多的
hook
给我们去扩展
- Bean实例化之前有
BeanFactoryPostProcessor
- Bean实例化之后,初始化时,有相关的
Aware
接口供我们去拿到Context
相关信息 - 环绕着初始化阶段,有
BeanPostProcessor
(AOP的关键) - 在初始化阶段,有各种的init方法供我们去自定义
而循环依赖的解决主要通过三级的缓存
- 在实例化后,会把自己扔到三级缓存(此时的key是BeanName,Value是ObjectFactory)
- 在注入属性时,发现
**A**
需要依赖B
,也会走B的实例化过程,B属性注入依赖A
,从三级缓存找到A
,删掉三级缓存,放到二级缓存