Spring bean 生命周期的概述:
bean的生命周期从调用beanFactory的getBean开始,到这个bean被销毁结束,可以总结为以下七个阶段:
- 处理名称,检查缓存
- 处理父子容器
- 处理dependson
- 选择scope策略
- 创建bean
- 类型转换处理
- 销毁bean
一.处理名称,检查缓存
- 首先处理别名,将别名解析为实际名称
- 对FactoryBean 做特殊处理,如果以 & 开头,表示要获取FactoryBean本身,否则表示要获取其产品
- 这里针对单例对象会检查一级,二级,三级缓存
- singletonFactories 三级缓存,存放单例工厂对象
- earlySingletonObjects 二级缓存,存放单例工厂的产品对象,可称为提前单例对象
- 如果发生循环依赖,产品是代理;没有发生循环依赖,产品是原始对象。(二三级缓存是为了解决循环依赖)
- 三级缓存可以解决循环依赖,为啥还要二级缓存?二级缓存是为了解决需要代理的情况下,又发生了循环依赖。
- singletonObjects 一级缓存,存放单例成品对象(看有没有创建好的单例对象,如果有,不用创建,起到加速作用,同样保证单例对象的唯一性)
二.处理父子容器
- 如果当前容器根据名字找不到这个bean,此时若父容器存在,则执行父容器getBean流程
- 父子容器的bean名称可以重复
三.处理dependsOn
- 如果当前bean有通过dependsOn指定了非显示依赖的bean,这一步会提前创建这些dependsOn的bean
- 所谓非显示依赖,就是两个bean之间不是直接依赖的关系,但需要控制它们的创建先后顺序
四.选择scope策略
- 对于 singleton scope,首先到单例池中获取bean,如果有则直接返回,如果没有再进入创建流程。
- 对于 prototype scope,每次都会进入创建流程。
- 对于自定义 scope,例如request,首先到request域中获取bean,如果有则直接返回,如果没有再进入创建流程。
五.创建bean
①创建bean实例
- 优先选择带@Autowired注解的构造
- 如有唯一的带参构造,也会入选
- 默认构造
② 依赖注入
- 注解匹配:@Autowired,@Value,@Response
- 名字类型匹配:Autowire_By_Name,Autowire_By_Type
- 精确指定
优先级比较:精确指定 > 名字类型匹配 > 注解匹配
③ 初始化
执行顺序:
- 先执行Aware接口的装配
- 注解@PostConstruct 标记的方法
- 处理InitializingBean接口定义的初始化方法
- 最后处理用 initMethod 的方法
④ 注册可销毁 bean
在这一步判断并登记可销毁 bean
- 判断依据
- 如果实现了 DisposableBean 或 AutoCloseable 接口,则为可销毁 bean
- 如果自定义了 destroyMethod,则为可销毁 bean
- 如果采用@Bean 没有指定 destroyMethod,则采用自动推断方式获取销毁方法名(close,shutdown)
- 如果有 @PreDestroy 标记的方法
- 存储位置
- singleton scope 的可销毁 bean 会存储于 beanFactory 的成员当中
- prototype scope 不会存储,需要自己找到此对象销毁
- 自定义 scope 的可销毁 bean 会存储于对应的域对象当中
- 存储时都会封装为 DisposableBeanAdapter 类型对销毁方法的调用进行适配
六.类型转换处理
- 如果 getBean 的 requiredType 参数与实际得到的对象类型不同,会尝试进行类型转换
七.销毁bean
- 销毁时机
- singleton bean 的销毁在ApplicationContext.close时,此时会找到所有 DisposableBean的名字,逐一销毁。
- 自定义 scope bean 的销毁在作用域对象生命周期结束时
- prototype bean 的销毁可以通过自己手动调用 AutowireCapableBeanFactory.destoryBean 方法执行销毁
- 同一 bean 中不同形式销毁方法的调用次序
- 优先后处理器销毁,即 @PreDestroy
- 其次 DisposableBean 接口销毁
- 最后 destroyMethod 销毁