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