Spring框架中的Bean生命周期

目录

Bean的实例化

BeanFactoryPostProcessor

属性赋值

循环依赖

初始化 

处理各种Aware接口

执行BeanPostProcessor前置处理

执行InitializingBean初始化方法或执行init-method自定义初始化方法 

 执行BeanPostProcessor后置处理 

销毁


Spring Bean 的生命周期总体分为四个阶段:

  •         实例化
  •         属性赋值
  •         初始化
  •         销毁

Bean的实例化

Spring容器在进行初始化时,会将xml或者配置类中配置的相关的类通过Java Proxy(反射)的方式创建出一个BeanDefinition对象,然后将所有的BeanDefinition对象存在一个beanDefinitionMap的集合中去,xml中配置的bean的id或者注解配置的value属性作为存入Map的key,整个BeanDefinition对象作为value保存。

BeanFactoryPostProcessor

BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,那么 Spring就会回调该接口的方法,用于对BeanDefinition注册和修改的功能。如果实现了这个接口并在其中完成了一些BeanDefinition的注册或修改,那么在Bean真正实例化之前,会先回调这个接口的方法,执行其中的逻辑,如果没有实现该接口,那么完成真正的实例化。

属性赋值

BeanDefinition 中有对当前Bean实体的注入信息通过属性propertyValues进行了存储,Spring在进行属性注入时,会分为如下几种情况:

  • 注入普通属性,String、int或存储基本类型的集合时,直接通过set方法的反射设置进去;
  • 注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没 有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;
  • 注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖)

循环依赖

多个实体之间相互依赖并形成闭环的情况就叫做"循环依赖",也叫做“循环引用”,当一个Bean对象中如果引用了另一个Bean对象时,会暂停自己的初始化,先将引用的那个Bean对象先创建出来,然后再继续自己的初始化过程;但在这个过程中,可能会出现引用的那个Bean对象中也引用了引用它的Bean对象,这个时候就会产生循环依赖的情况。

为了解决循环依赖,Spring提供了三级缓存存储完整的Bean实例和半成品的Bean实例:

  • 最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存" Map singletonObjects = new ConcurrentHashMap(256);
  • 早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存" Map earlySingletonObjects = new ConcurrentHashMap(16);
  • 单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三 级缓存" Map> singletonFactories = new HashMap(16);

有了三级缓存的后,在属性赋值阶段会如果某个Bean中引用其他Bean,那么会依次从“三级缓存”往“一级缓存”中找,避免了循环依赖的问题。

初始化 

经过Bean的实例化和属性赋值后的Bean其实还并不是一个完整的Bean实例对象,而是一个“半成品”,在完成它的初始化后才会成为一个完整的Bean实例对象并存放进到一个名为singletonObjects的Map中,最后当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回。

初始化的过程有以下几个关键点:

处理各种Aware接口

Aware接口是一种框架辅助属性注入的一种思想,为Bean生命周期各个阶段提供扩展。

  • 如果Bean实现BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,注入Bean的名字;
  • 如果Bean实现BeanClassLoaderAware接口,调用setBeanClassLoader()方法,注入ClassLoader对象的实例;
  • 如果Bean实现BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,注入的是Spring工厂;
  • 如果Bean实现ApplicationContextAware接口,会调用setApplicationContext()方法,注入Spring上下文;

执行BeanPostProcessor前置处理

Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程, 例如:属性的填充、初始方法init的执行等,其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后 处理。跟Bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的BeanPostProcessor, 会在流程节点上被Spring自动调用。

执行InitializingBean初始化方法或执行init-method自定义初始化方法 

  • 如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。
  • 如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。 

 执行BeanPostProcessor后置处理 

如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法,由于这个方法是在Bean初始化结束后调用;

在结束以上初始化的所有过程之后,就创建出了一个完整的Bean实例对象,我们就可以通过applicationContext.getBean(beanName)使用真正的Bean对象了。

销毁

销毁一个Bean对象有两种方式:

  • 执行DisposableBean销毁Bean: 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法执行销毁;
  • 执行destroy-method自定义销毁方法: 如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的自定义销毁方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值