0%

Spring中Bean的生命周期总结

总结一下Spring中Bean的生命周期,对于具体的源码分析以前写过文档,网上也有很多类似的文章,这里不做重复。

简单版的

Spring中Bean的生命周期或者说任何一个物体的生命周期都可以大体分为:初始化、使用、销毁,哪怕是Spring IOC容器也可以这样总结。这里说要总结生命周期,其实就是把这三步稍微详细的再说一下。大体的过程如下:

  1. 手动或者自动的触发获取一个Bean,使用BeanFactory的时候需要我们代码自己获取Bean,ApplicationContext则是在IOC启动的时候自动初始化一个Bean。
  2. IOC会根据BeanDefinition来实例化这个Bean,如果这个Bean还有依赖其他的Bean则会先初始化依赖的Bean,这里又涉及到了循环依赖的解决。实例化Bean的时候根据工厂方法、构造方法或者简单初始化等选择具体的实例来进行实例化,最终都是使用反射进行实例化。
  3. Bean实例化完成,也就是一个对象实例化完成后,会继续填充这个Bean的各个属性,也是使用反射机制将属性设置到Bean中去。
  4. 填充完属性后,会调用各种Aware方法,将需要的组件设置到当前Bean中。BeanFactory这种低级容器需要我们手动注册Aware接口,而ApplicationContext这种高级容器在IOC启动的时候就自动给我们注册了Aware等接口。
  5. 接下来如果Bean实现了PostProcessor一系列的接口,会先调用其中的postProcessBeforeInitialization方法。BeanFactory这种低级容器需要我们手动注册PostProcessor接口,而ApplicationContext这种高级容器在IOC启动的时候就自动给我们注册了PostProcessor等接口。
  6. 如果Bean实现了InitializingBean接口,则会调用对应的afterPropertiesSet方法。
  7. 如果Bean设置了init-method属性,则会调用init-method指定的方法。
  8. 接下来如果Bean实现了PostProcessor一系列的接口,会先调用其中的postProcessAfterInitialization方法。BeanFactory这种低级容器需要我们手动注册PostProcessor接口,而ApplicationContext这种高级容器在IOC启动的时候就自动给我们注册了PostProcessor等接口。
  9. 到这里Bean就可以使用了。
  10. 容器关闭的时候需要销毁Bean。
  11. 如果Bean实现了DisposableBean,则调用destroy方法。
  12. 如果Bean配置了destroy-method属性,则调用指定的destroy-method方法。

在实例化完Bean和填充属性之前还会涉及到AOP的处理,在处理依赖Bean的时候还会涉及到循环依赖的处理等等细节。

复杂版的

  1. 手动或者自动的触发获取一个Bean,使用BeanFactory的时候需要我们代码自己获取Bean,ApplicationContext则是在IOC启动的时候自动初始化一个Bean。
  2. IOC会根据BeanDefinition来实例化这个Bean,如果这个Bean还有依赖其他的Bean则会先初始化依赖的Bean,这里又涉及到了循环依赖的解决。
  3. 实例化之前先看下Bean是否实现了InstantiationAwareBeanPostProcessor接口,如果实现了该接口,则先调用其postProcessBeforeInstantiation方法,常见的实现是在AbstractAutoCreator中有该方法的实现,在这里可以根据实际情况返回一个代理,如果这里返回了一个代理Bean而不是返回null的话,下面的步骤就不会继续进行下去了。换句话说,如果这里生成了Bean就不需要下面的步骤进行Bean的实例化和初始化了。
  4. 如果上面一步返回了一个Bean,虽然不需要继续下面的实例化步骤,但是还是需要走一下postProcessBeforeInstantiation的postProcessAfterInitialization方法,就是不管怎么样生成Bean,最后都要走一下初始化的后置处理器。
  5. 如果上面没有生成一个Bean,就继续正常的实例化Bean,实例化Bean的时候根据工厂方法、构造方法或者简单初始化等选择具体的实例来进行实例化,最终都是使用反射进行实例化。
  6. Bean实例化完成,也就是一个对象实例化完成后,如果改Bean实现了MergedBeanDefinitionPostProcessor接口,则调用这个接口的postProcessMergedBeanDefinition方法,这里我们熟悉的有:对@Autowired, @Value, @Inject等注解进行预解析;对@Resource, @PostConstruct, @PreDestroy等注解进行预解析。
  7. 经过对一些注解的预解析之后,会进行循环依赖的一些准备工作,如果需要提前曝光的话,会把还在生成的Bean放到singletonFactories中去,解决循环依赖的时候会用到。
  8. 然后会继续填充这个Bean的各个属性,在填充属性前,还需要看是否实现了InstantiationAwareBeanPostProcessor接口,如果实现了该接口,则需要调用其postProcessAfterInstantiation方法,如果有一个实现的该方法返回了false,表示不需要继续再进行下面的填充属性设置,也不需要再继续处理其他的InstantiationAwareBeanPostProcessor。
  9. 如果上一步的处理没有直接返回false,而是继续处理的话,还是会继续判断有没有实现InstantiationAwareBeanPostProcessor接口,如果实现了该接口则需要调用其postProcessPropertyValues方法,这里会有我们熟悉的动作:对@Autowired, @Value, @Inject等注解的依赖进行设值、对@Resource, @PostConstruct, @PreDestroy等注解的依赖进行设值,都是通过反射将依赖设置到目标Bean中去;还有一个对@Required所注解的必须依赖进行校验,如果没有就会抛异常。
  10. 接下来如果有depends-on属性的话,需要进行依赖检查,不满足依赖会抛异常。
  11. 这里就是真正填充属性的地方了,使用反射机制将属性设置到Bean中去。
  12. 填充完属性后,会调用各种Aware方法,将需要的组件设置到当前Bean中。BeanFactory这种低级容器需要我们手动注册Aware接口,而ApplicationContext这种高级容器在IOC启动的时候就自动给我们注册了Aware等接口。
  13. 接下来如果Bean实现了PostProcessor一系列的接口,会先调用其中的postProcessBeforeInitialization方法。BeanFactory这种低级容器需要我们手动注册PostProcessor接口,而ApplicationContext这种高级容器在IOC启动的时候就自动给我们注册了PostProcessor等接口。实现类大概如下:ApplicationContextAwareProcessor在该方法中会执行各种ApplicationContext的Aware方法,比如ApplicationContextAware、ResourceLoaderAware等;InitDestroyAnnotationBeanPostProcessor在该方法中会调用注解的init方法,也就是@PostConstruct注解的方法,比下面的InitializingBean和xml中的init-method执行要早。
  14. 如果Bean实现了InitializingBean接口,则会调用对应的afterPropertiesSet方法。
  15. 如果Bean设置了init-method属性,则会调用init-method指定的方法,使用反射调用。
  16. 接下来如果Bean实现了PostProcessor一系列的接口,会先调用其中的postProcessAfterInitialization方法。BeanFactory这种低级容器需要我们手动注册PostProcessor接口,而ApplicationContext这种高级容器在IOC启动的时候就自动给我们注册了PostProcessor等接口。实现类大概如下:AbstractAutoProxyCreator会在该方法看是否需要进行代理;
  17. 接下来继续注册DisposableBean。
  18. 到这里Bean就可以使用了。
  19. 容器关闭的时候需要销毁Bean。
  20. 如果Bean实现了DisposableBean,则调用destroy方法。
  21. 如果Bean配置了destroy-method属性,则调用指定的destroy-method方法。
坚持原创技术分享,您的支持将鼓励我继续创作!
Fork me on GitHub