在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近吧整个流程化成了一个流程图。待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程。注意因为代码比较多,这里的流程图只画出了大概的流程,具体的可以深入代码

一、获取Bea

第一阶段获取Bean

这里的流程图的入口在 AbstractBeanFactory类的 doGetBean方法,这里可以配合前面的 getBean方法分析文章进行阅读。主要流程就是

1、先处理Bean 的名称,因为如果以“&”开头的Bean名称表示获取的是对应的FactoryBean对象;
2、从缓存中获取单例Bean,有则进一步判断这个Bean是不是在创建中,如果是的就等待创建完毕,否则直接返回这个Bean对象
3、如果不存在单例Bean缓存,则先进行循环依赖的解析
4、解析完毕之后先获取父类BeanFactory,获取到了则调用父类的getBean方法,不存在则先合并然后创建Bean

二、创建Bean

2.1 创建Bean之前

在真正创建Bean之前逻辑

这个流程图对应的代码在 AbstractAutowireCapableBeanFactory类的 createBean方法中。

1、这里会先获取 RootBeanDefinition对象中的Class对象并确保已经关联了要创建的Bean的Class 。整编:微信公众号,搜云库技术团队,ID:souyunku
2、这里会检查3个条件

(1)Bean的属性中的 beforeInstantiationResolved字段是否为true,默认是false。
(2)Bean是原生的Bean
(3)Bean的 hasInstantiationAwareBeanPostProcessors属性为true,这个属性在Spring准备刷新容器钱转杯BeanPostProcessors的时候会设置,如果当前Bean实现了 InstantiationAwareBeanPostProcessor则这个就会是true。

当三个条件都存在的时候,就会调用实现的 InstantiationAwareBeanPostProcessor接口的 postProcessBeforeInstantiation方法,然后获取返回的Bean,如果返回的Bean不是null还会调用实现的 BeanPostProcessor接口的 postProcessAfterInitialization方法,这里用代码说明

  1. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  2. Object bean = null;
  3. //条件1
  4. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  5. //条件2跟条件3
  6. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  7. Class<?> targetType = determineTargetType(beanName, mbd);
  8. if (targetType != null) {
  9. //调用实现的postProcessBeforeInstantiation方法
  10. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
  11. if (bean != null) {
  12. //调用实现的postProcessAfterInitialization方法
  13. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  14. }
  15. }
  16. }
  17. //不满足2或者3的时候就会设置为false
  18. mbd.beforeInstantiationResolved = (bean != null);
  19. }
  20. return bean;
  21. }

1、如果上面3个条件其中一个不满足就不会调用实现的方法。默认这里都不会调用的这些 BeanPostProcessors的实现方法。然后继续执行后面的 doCreateBean方法。

2.1 真正的创建Bean,doCreateBean

doCreateBean方法逻辑

这个代码的实现还是在 AbstractAutowireCapableBeanFactory方法中。流程是

1、先检查 instanceWrapper变量是不是null,这里一般是null,除非当前正在创建的Bean在 factoryBeanInstanceCache中存在这个是保存还没创建完成的FactoryBean的集合。
2、调用createBeanInstance方法实例化Bean,这个方法在后面会讲解
3、如果当前 RootBeanDefinition对象还没有调用过实现了的 MergedBeanDefinitionPostProcessor接口的方法,则会进行调用 。整编:微信公众号,搜云库技术团队,ID:souyunku
4、 当满足以下三点
(1)是单例Bean
(2)尝试解析bean之间的循环引用
(3)bean目前正在创建中
则会进一步检查是否实现了 SmartInstantiationAwareBeanPostProcessor接口如果实现了则调用是实现的 getEarlyBeanReference方法 5、 调用 populateBean方法进行属性填充,这里后面会讲解 6、 调用 initializeBean方法对Bean进行初始化,这里后面会讲解

2.1.1 实例化Bean,createBeanInstance

实例化Bean

这里的逻辑稍微有一点复杂,这个流程图已经是简化过后的了。简要根据代码说明一下流程

  1. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
  2. //步骤1
  3. Class<?> beanClass = resolveBeanClass(mbd, beanName);
  4.  
  5. if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
  6. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  7. "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
  8. }
  9. //步骤2
  10. Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
  11. if (instanceSupplier != null) {
  12. return obtainFromSupplier(instanceSupplier, beanName);
  13. }
  14. //步骤3
  15. if (mbd.getFactoryMethodName() != null) {
  16. return instantiateUsingFactoryMethod(beanName, mbd, args);
  17. }
  18.  
  19. boolean resolved = false;
  20. boolean autowireNecessary = false;
  21. if (args == null) {
  22. synchronized (mbd.constructorArgumentLock) {
  23. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  24. resolved = true;
  25. autowireNecessary = mbd.constructorArgumentsResolved;
  26. }
  27. }
  28. }
  29. //步骤4.1
  30. if (resolved) {
  31.  
  32. if (autowireNecessary) {
  33. return autowireConstructor(beanName, mbd, null, null);
  34. }
  35. else {
  36.  
  37. return instantiateBean(beanName, mbd);
  38. }
  39. }
  40.  
  41. //步骤4.2
  42. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  43. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
  44. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  45. return autowireConstructor(beanName, mbd, ctors, args);
  46. }
  47.  
  48. //步骤5
  49. ctors = mbd.getPreferredConstructors();
  50. if (ctors != null) {
  51. return autowireConstructor(beanName, mbd, ctors, null);
  52. }
  53.  
  54. return instantiateBean(beanName, mbd);
  55. }

1、先检查Class是否已经关联了,并且对应的修饰符是否是public的
2、如果用户定义了Bean实例化的函数,则调用并返回
3、如果当前Bean实现了 FactoryBean接口则调用对应的 FactoryBean接口的 getObject方法
4、根据getBean时候是否传入构造参数进行处理
4.1 如果没有传入构造参数,则检查是否存在已经缓存的无参构造器,有则使用构造器直接创建,没有就会调用 instantiateBean方法先获取实例化的策略默认是 CglibSubclassingInstantiationStrategy,然后实例化Bean。最后返回
4.2 如果传入了构造参数,则会先检查是否实现了 SmartInstantiationAwareBeanPostProcessor接口,如果实现了会调用 determineCandidateConstructors获取返回的候选构造器。整编:微信公众号,搜云库技术团队,ID:souyunku
4.3 检查4个条件是否满足一个
(1)构造器不为null,
(2)从RootBeanDefinition中获取到的关联的注入方式是构造器注入(没有构造参数就是setter注入,有则是构造器注入)
(3)含有构造参数
(4)getBean方法传入构造参数不是空

满足其中一个则会调用返回的候选构造器实例化Bean并返回,如果都不满足,则会根据构造参数选则合适的有参构造器然后实例化Bean并返回

5、如果上面都没有合适的构造器,则直接使用无参构造器创建并返回Bean。

2.1.2 填充Bean,populateBean

填充Bean

这里还是根据代码来说一下流程

  1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  2. if (bw == null) {
  3. if (mbd.hasPropertyValues()) {
  4. throw new BeanCreationException(
  5. mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
  6. }
  7. else {
  8. // Skip property population phase for null instance.
  9. return;
  10. }
  11. }
  1. boolean continueWithPropertyPopulation = true;
  2. //步骤1
  3. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  4. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  5. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  6. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  7. if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
  8. continueWithPropertyPopulation = false;
  9. break;
  10. }
  11. }
  12. }
  13. }
  14.  
  15. if (!continueWithPropertyPopulation) {
  16. return;
  17. }
  18. //步骤2--------------------
  19. PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
  20.  
  21. int resolvedAutowireMode = mbd.getResolvedAutowireMode();
  22. if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
  23. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
  24. // Add property values based on autowire by name if applicable.
  25. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
  26. autowireByName(beanName, mbd, bw, newPvs);
  27. }
  28. // Add property values based on autowire by type if applicable.
  29. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
  30. autowireByType(beanName, mbd, bw, newPvs);
  31. }
  32. pvs = newPvs;
  33. }
  34.  
  35. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  36. boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
  37.  
  38. PropertyDescriptor[] filteredPds = null;
  39. //步骤3
  40. if (hasInstAwareBpps) {
  41. if (pvs == null) {
  42. pvs = mbd.getPropertyValues();
  43. }
  44. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  45. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  46. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  47. PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
  48. if (pvsToUse == null) {
  49. if (filteredPds == null) {
  50. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  51. }
  52. pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  53. if (pvsToUse == null) {
  54. return;
  55. }
  56. }
  57. pvs = pvsToUse;
  58. }
  59. }
  60. }
  61. if (needsDepCheck) {
  62. if (filteredPds == null) {
  63. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  64. }
  65. checkDependencies(beanName, mbd, filteredPds, pvs);
  66. }
  67. //步骤4
  68. if (pvs != null) {
  69. applyPropertyValues(beanName, mbd, bw, pvs);
  70. }
  71. }
  1.  

1、检查当前Bean是否实现了 InstantiationAwareBeanPostProcessor的 postProcessAfterInstantiation方法则调用,并结束Bean的填充。
2、将按照类型跟按照名称注入的Bean分开,如果注入的Bean还没有实例化的这里会实例化,然后放到 PropertyValues对象中。
3、如果实现了 InstantiationAwareBeanPostProcessor类的 postProcessProperties则调用这个方法并获取返回值,如果返回值是null,则有可能是实现了过期的 postProcessPropertyValues方法,这里需要进一步调用 postProcessPropertyValues方法
4、进行参数填充

2.1.3 初始化Bean,initializeBean

初始化Bean

同时这里根据代码跟流程图来说明

1、如果Bean实现了 BeanNameAwareBeanClassLoaderAwareBeanFactoryAware则调用对应实现的方法 。整编:微信公众号,搜云库技术团队,ID:souyunku
2、Bean不为null并且bean不是合成的,如果实现了 BeanPostProcessor的 postProcessBeforeInitialization则会调用实现的 postProcessBeforeInitialization方法。在 ApplicationContextAwareProcessor类中实现了 postProcessBeforeInitialization方法。而这个类会在Spring刷新容器准备 beanFactory的时候会加进去,这里就会被调用,而调用里面会检查Bean是不是 EnvironmentAwareEmbeddedValueResolverAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAwareApplicationContextAware的实现类。这里就会调用对应的实现方法。代码如下

  1. protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  2. .......
  3. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  4. .......
  1. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  2. if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
  3. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
  4. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
  5. return bean;
  6. }
  7.  
  8. AccessControlContext acc = null;
  9.  
  10. if (System.getSecurityManager() != null) {
  11. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
  12. }
  13.  
  14. if (acc != null) {
  15. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  16. invokeAwareInterfaces(bean);
  17. return null;
  18. }, acc);
  19. }
  20. else {
  21. invokeAwareInterfaces(bean);
  22. }
  23.  
  24. return bean;
  25. }

1、实例化Bean然后,检查是否实现了 InitializingBean的 afterPropertiesSet方法,如果实现了就会调用
2、Bean不为null并且bean不是合成的,如果实现了 BeanPostProcessor的 postProcessBeforeInitialization则会调用实现的 postProcessAfterInitialization方法。

到此创建Bean 的流程就没了,剩下的就是容器销毁的时候的了

三、destory方法跟销毁Bean

Bean在创建完毕之后会检查用户是否指定了 destroyMethodName以及是否实现了 DestructionAwareBeanPostProcessor接口的 requiresDestruction方法,如果指定了会记录下来保存在 DisposableBeanAdapter对象中并保存在bean的 disposableBeans属性中。代码在 AbstractBeanFactory的 registerDisposableBeanIfNecessary

  1. protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
  2. ......
  3. registerDisposableBean(beanName,
  4. new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
  5. ......
  6. }
  1. public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
  2. List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
  3. .......
  4. String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
  5. if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
  6. !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
  7. ......
  8. this.destroyMethod = destroyMethod;
  9. }
  10. this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
  11. }

在销毁Bean的时候最后都会调用 AbstractAutowireCapableBeanFactory的 destroyBean方法。

  1. public void destroyBean(Object existingBean) {
  2. new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();
  3. }

这里是创建一个 DisposableBeanAdapter对象,这个对象实现了Runnable接口,在实现的 run方法中会调用实现的 DisposableBean接口的 destroy方法。并且在创建 DisposableBeanAdapter对象的时候会根据传入的bean是否实现了 DisposableBean接口来设置 invokeDisposableBean变量,这个变量表实有没有实现 DisposableBean接口

  1. public DisposableBeanAdapter(Object bean, List<BeanPostProcessor> postProcessors, AccessControlContext acc) {
  2. Assert.notNull(bean, "Disposable bean must not be null");
  3. this.bean = bean;
  4. this.beanName = bean.getClass().getName();
  5. //根据传入的bean是否实现了`DisposableBean`接口来设置`invokeDisposableBean`变量
  6. this.invokeDisposableBean = (this.bean instanceof DisposableBean);
  7. this.nonPublicAccessAllowed = true;
  8. this.acc = acc;
  9. this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
  10. }
  11.  
  12. public void destroy() {
  13. ......
  14. //根据invokeDisposableBean决定是否调用destroy方法
  15. if (this.invokeDisposableBean) {
  16. if (logger.isTraceEnabled()) {
  17. logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
  18. }
  19. try {
  20. if (System.getSecurityManager() != null) {
  21. AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
  22. ((DisposableBean) this.bean).destroy();
  23. return null;
  24. }, this.acc);
  25. }
  26. else {
  27. ((DisposableBean) this.bean).destroy();
  28. }
  29. }
  30. catch (Throwable ex) {
  31. String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
  32. if (logger.isDebugEnabled()) {
  33. logger.warn(msg, ex);
  34. }
  35. else {
  36. logger.warn(msg + ": " + ex);
  37. }
  38. }
  39. }
  40. ......
  41. }

四、总结。

最后来一个大的流程

实例化前的准备阶段

实例化前

实例化后

初始化前

————————————————

本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。
传送门:https://mp.weixin.qq.com/s/osB-BOl6W-ZLTSttTkqMPQ

Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析的更多相关文章

  1. Spring中Bean生命周期

    Spring中的bean生命周期是一个重要的点,只有理解Bean的生命周期,在开发中会对你理解代码是非常有用的.对于Bean的周期,个人认为可以分为四个阶段.第一阶段:Bean的实例化,在该阶段主要是 ...

  2. Spring:Bean生命周期

    关于Bean生命周期,我在网上找了两张图: 图1: 图2: 总结起来就是: Bean构建: Bean对象创建 > @Autowired | @Resource> @PostConstruc ...

  3. Spring的Bean生命周期理解

    首先,在经历过很多次的面试之后,一直不能很好的叙述关于springbean的生命周期这个概念.今日对于springBean的生命周期进行一个总结. 一.springBean的生命周期: 如下图所示: ...

  4. 2.Spring的Bean生命周期和组装方式

    1.Spring IoC容器概述 Spring IoC容器: Spring容器即体现了IoC原理    Spring容器通过读取配置元数据负责对Beans实例化.配置和装配     配置元数据可以用X ...

  5. spring学习笔记(四)我对spring中bean生命周期的理解

    我相信大部分同学对spring中bean的生命周期都不陌生,但是如果要详细的说出每一个步骤,可能能说出来的也不多,我之前也是这样,前几天调了一下spring的源码,看了一点书,突然一下明朗了,理解了s ...

  6. spring注解-bean生命周期

    https://www.jianshu.com/p/70b935f2b3fe bean的生命周期 bean创建---初始化----销毁的过程 容器管理bean的生命周期 对象创建:容器启动后调用bea ...

  7. Spring配置文件-Bean生命周期配置(init-method方法,destory-method方法)

    1.UserDaoImpl类 public class UserDaoImpl implements UserDao { public UserDaoImpl(){ System.out.printl ...

  8. [转]Spring 之 Bean 生命周期

    Spring 容器中可以注册多个后处理器,只要它们同时实现 org.springframework.core.Ordered 接口. 下载文件 :内容来自 <精通Spring+4.x++企业应用 ...

  9. Spring源码系列 — Bean生命周期

    前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...

随机推荐

  1. 图像滤波—opencv函数

      函数原型 方框滤波 ,-), bool normalize = true, int borderType = BORDER_DEFAULT) 均值滤波 ,-), int borderType = ...

  2. 【译】用 `Wasmer` 进行插件开发 1

    [译]用 Wasmer 进行插件开发 1 Using Wasmer for Plugins Part 1 译文 原文链接 https://wiredforge.com/blog/wasmer-plug ...

  3. http断点续传的原理

    ——————————————先讲原理,如下:—————————————————— 举一个详细的例子: 一般场景,要访问的域名:www.jizhuomi.com/android,文件名为down.zip ...

  4. Codeforces Round #525 (Div. 2) C. Ehab and a 2-operation task 数学 mod运算的性质

    C. Ehab and a 2-operation task 数学 mod运算的性质 题意: 有两种对前缀的运算 1.对前缀每一个\(a +x\) 2.对前缀每一个\(a\mod(x)\) 其中x任选 ...

  5. HTTP头部字段总结【转】

    原作者: 留七七, 地址:http://www.jianshu.com/p/6e86903d74f7 一.常用标准请求头字段 Accept  设置接受的内容类型 Accept-Charset    设 ...

  6. Linux上查看当前系统各内存分区信息

    命令 ulimit -a -a 查看所有信息,同理,也可以例如 ulimit -s 只查看栈占内存信息

  7. Wx-小程序中使用伪类选择器实现border-1px

    .borders::before{ position: absolute; left:; top:; content: " "; width: 100%; height: 1px; ...

  8. css transform 2D3D转换

    2D转换 translate 移动 <style> div{ width: 100px; height: 100px; } .box{ border: 1px dashed red; fl ...

  9. 「题解」「BZOJ-4668」冷战

    题目 点这里 思路及代码 我们可以使用并查集的按秩合并(但是不要路径压缩). 两个集合被合并起来,连上的边的权值就设为当前时间. 然后我们可以发现,询问 \(j\) 与 \(k\) 何时联通,就是查询 ...

  10. Windows10_64位搭建WampServer(运行php代码)教程及问题

    Windows10_64位搭建WampServer(运行php代码)教程及问题    笔者最近学习PHP,想通过web页面的形式更加形象生动的了解php代码的原理.     于是,这次就通过WampS ...