Spring IOC之Bean的生命周期

一、Bean的生命周期

Bean的生命周期可以分为三大部分:Bean的获取、Bean的使用、Bean的销毁。

1、Bean的获取

Bean的获取主要是在AbstractBeanFactory的getBean方法中。

A、getBean方法调用过程

  1. AbstractBeanFactory getBean
    1. AbstractBeanFactory doGetBean
      1. AbstractBeanFactory transformedBeanName
      2. AbstractBeanFactory getSingleton(从缓存中获取Bean实例,若实际是从三级缓存中获取Bean实例,则会调用对应的Bean工厂方法并添加到二级缓存
      3. 【AbstractBeanFactory getObjectForBeanInstance】
      4. AbstractBeanFactory  getMergedLocalBeanDefinition(从BeanDefinitionMap中获取对应BeanName的BeanDefinition)
      5. AbstractBeanFactory getSingleton(Bean实例的获取)
        1. this.singletonObjects.get(beanName)(从一级缓存获取Bean实例)
        2. singletonFactory.getObject()(一级缓存为空,则创建Bean
          1. AbstractAutowireCapableBeanFactory createBean
            1. AbstractAutowireCapableBeanFactory resolveBeforeInstantiation
              1. AbstractAutowireCapableBeanFactory applyBeanPostProcessorsBeforeInstantiation
                1. InstantiationAwareBeanPostProcessor postProcessBeforeInstantiation
            2. AbstractAutowireCapableBeanFactory doCreateBean
              1. AbstractAutowireCapableBeanFactory createBeanInstance(推断构造方法并创建Bean实例)
              2. AbstractAutowireCapableBeanFactory applyMergedBeanDefinitionPostProcessors
                1. MergedBeanDefinitionPostProcessor postProcessMergedBeanDefinition
                  1. InitDestroyAnnotationBeanPostProcessor postProcessMergedBeanDefinition
                    1. LifecycleMetadata metadata = findLifecycleMetadata(beanType)(找到该Bean Class所有声明了@PostConstruct和@PreDestroy注解的方法)
              3. 【DefaultSingletonBeanRegistry addSingletonFactory】(单例&允许循环依赖&是否当前创建中成立,则暴露半成品bean实例到三级缓存
              4. AbstractAutowireCapableBeanFactory populateBean(属性注入)
                1. InstantiationAwareBeanPostProcessor postProcessAfterInstantiation(若重写了该方法,则可以提前实例化并返回)
                2. AbstractAutowireCapableBeanFactory autowireByName
                3.  AbstractAutowireCapableBeanFactory autowireByType
                4. InstantiationAwareBeanPostProcessor postProcessProperties
                5. InstantiationAwareBeanPostProcessor postProcessPropertyValues
                6.  AbstractAutowireCapableBeanFactory applyPropertyValues
              5. AbstractAutowireCapableBeanFactory initializeBean(初始化Bean实例)
                1. AbstractAutowireCapableBeanFactory invokeAwareMethod(调用Bean实现的aware接口的方法)
                  1. BeanClassLoaderAware setBeanName
                  2. BeanClassLoaderAware setBeanClassLoader
                  3. BeanFactoryAware setBeanFactory
                2. 【AbstractAutowireCapableBeanFactory applyBeanPostProcessorsBeforeInitialization】(对Bean进行初始化前处理)
                  1. BeanPostProcessor postProcessBeforeInitialization
                    1. InitDestroyAnnotationBeanPostProcessor postProcessBeforeInitialization
                      1. LifecycleMetadata invokeInitMethods(调用@PostConstruct声明的方法
                3. AbstractAutowireCapableBeanFactory invokeInitMethods(对Bean进行初始化处理)
                  1. InitializingBean afterPropertiesSet
                  2. AbstractAutowireCapableBeanFactory invokeCustomInitMethod(调用bean设置的initMethod)
                4. 【AbstractAutowireCapableBeanFactory applyBeanPostProcessorsAfterInitialization】(对Bean进行初始化后处理)
                  1. BeanPostProcessor postProcessBeforeInitialization
      6. DefaultSingletonBeanRegistry addSingleton(添加bean到一级缓存

B、getBean方法步骤总结

<1>【推断构造方法】

Spring根据某个类去实例化bean之前,需要先推断出该使用哪个构造方法:

  • 若只有一个构造方法,则会用这个构造方法;
  • 若有多个构造方法,则必须有无参构造方法,否则会报错;可以通过@Autowire标注使用该构造方法,但不可用给多个构造方法标注@Autowire;

<2>【实例化bean】

 先判断是否实现了InstantiationAwareBeanPostProcessor接口,是则可以提前返回该beanName的实例对象,否则根据beanName找到对应的classType,然后利用对应的类进行反射创建对象。

<3>【依赖注入(也叫属性注入)】

依赖注入的核心方法是populateBean,其中的autowireByName和autowireByType方法对应注解@Autowire和@Resource

<4>【调用bean实现的aware接口设置bean的信息】

比如BeanNameAware设置bean的名称、BeanFactoryAware设置bean的工厂,ApplicationContextAware设置bean的容器等

<5>【调用BeanPostProcessor的初始化前方法】

  • @PostConstruct的设置:

        容器初始化的时候会实例化CommonAnnotationBeanPostProcessor,实例过程会调用里面的setInitAnnotationType(PostConstruct.class)和setDestroyAnnotationType(PreDestroy.class)方法。

  • @PostConstruct的调用:

        Bean实例化过程中的调用Bean的初始化前方法阶段,会去调用InitDestroyAnnotationBeanPostProcessor初始化前方法,该方法的执行过程如下:

  1. 调用findLifecycleMetadata(bean.getClass())找到所有声明了@PostConstruct注解的方法。
  2. 调用metadata.invokeInitMethods(bean, beanName)执行1找到的方法。

<6>【调用bean实现的InitialzingBean接口的afterPropertiesSet方法】

<7>【进行初始化】

调用@Bean设置的initMethod方法

<8>【调用BeanPostProcessor的初始化后方法】

包括进行AOP等。

2、Bean的使用

3、Bean的销毁(当Spring上下文关闭会对bean进行销毁)

(1)【调用bean实现的DisposableBean的destroy方法】

(2)【调用@Bean设置的destroyMethod方法】

二、Spring解决循环依赖的方法-三级缓存

Spring通过利用三级缓存来解决循环依赖的问题。

Spring三级缓存:

  • 一级缓存:存储完整的bean实例
  • 二级缓存:存储半成品bean实例(若bean实现了AOP,则这里存储的是该bean的动态代理对象)。二级缓存会在A找B的时候调用。
  • 三级缓存:存储生产Bean的工厂方法。若bean使用了AOP,则会调用工厂方法生成bean的动态代理对象,否则返回半成品bean实例。三级缓存会在A找B,B找A的时候调用。

问题1:为什么需要三级缓存?

实际上,对于只有死循环的问题,二级缓存就可以可以解决,在实例化后(未初始化)把半成品bean实例提前放入二级缓存,这样当其他bean需要使用该bean实例时候,可以提前拿到。但是若bean实例使用了AOP,则需要为bean实例创建代理对象,为了在多重循环依赖(A依赖B,B依赖A,A依赖C,C依赖A)下,避免重复创建代理对象,所以需要通过三级缓存去创建代理对象存储到二级缓存,保证二级缓存中代理对象的唯一性。

问题2:Spring有没有解决构造函数参数bean的循环依赖问题?

Spring并没有解决构造函数参数bean的循环依赖问题,构造函数的循环依赖依然会报错,可以通过人工进行解决:在构造函数上加上@Lazy,@Lazy不会立即创建依赖的bean,而是先创建bean的代理对象,等到第一次用到才会利用实际bean对象进行替换。

  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值