前言

此篇是补充上篇未分析完的finishBeanFactoryInitialization部分
配合上篇食用效果更佳

Spring启动过程——源码分析

finishBeanFactoryInitialization(beanFactory)

主要方法preInstantiateSingletons()
遍历List beanNames
如果Bean 不是抽象&是单例&不是lazy

如果不是FactoryBean

getBean进入doGetBean 下面四张图都是
doGetBean.1

doGetBean.2 doGetBean.3 doGetBean.4 如果是bean是单例
重点方法 getSingleton 大致执行如下

   //先从缓存中取 第一次进来时没有值的Object singletonObject = this.singletonObjects.get(beanName);//存在 则returnif(singletonObject!=null) return;//解决循环依赖beforeSingletonCreation(beanName);//真正创建beansingletonObject = singletonFactory.getObject();afterSingletonCreation(beanName);//加入缓存addSingleton(beanName, singletonObject);return singleObject
复制代码

真正创建Bean是createBean() 如果是bean是多例

    //this.prototypesCurrentlyInCreation.set(beanName)beforePrototypeCreation(beanName);  prototypeInstance = createBean(beanName, mbd, args);//this.prototypesCurrentlyInCreation.remove()afterPrototypeCreation(beanName);
复制代码

单例多例创建Bean都会调用到createBean

真正创建Bean是createBean()

//一般用于创建aop代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//如果上边没有代理 这里会真正开始创建
Object beanInstance = doCreateBean(beanName, mbdToUse, args)
复制代码

createBean->resolveBeforeInstantiation

doCreateBean.1 doCreateBean.2 doCreateBean.3 走向如下面流程图 doCreateBean->createBeanInstance

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
bp instanceof MergedBeanDefinitionPostProcessor -> bp.postProcessMergedBeanDefinition(mbd, beanType, beanName)

populateBean

为刚刚实例化好的Bean进行属性等赋值

  • BeanWrapper为null直接报错或者return

  • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
    官方的解释是:让用户可以自定义属性注入。比如用户实现一 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过 postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。当然,如果无 特殊需求,直接使用配置中的信息注入即可。另外,Spring 并不建议大家直接实现 InstantiationAwareBeanPostProcessor 接口,如果想实现这种类型的后置处理器,更建议 通过继承 InstantiationAwareBeanPostProcessorAdapter 抽象类实现自定义后置处理器

  • 这里会出现一个Spring的内部processor:AutowiredAnnotationBeanPostProcessor 执行下去 进入postProcessProperties 首先找出所有的注解包括@Value @Autowired然后进行调用inject方法进行赋值 最终是通过反射实现最终赋值
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
复制代码

applyPropertyValues(beanName, mbd, bw, pvs);
将属性应用到 bean 对象中

  • 检测属性值列表是否已转换过的,若转换过,则直接填充属性,无需再次转换

  • 遍历属性值列表 pvs,解析原始值 originalValue,得到解析值 resolvedValue

  • 对解析后的属性值 resolvedValue 进行类型转换

  • 将类型转换后的属性值设置到 PropertyValue 对象中,并将 PropertyValue 对象存入 deepCopy 集合中

  • 将 deepCopy 中的属性信息注入到 bean 对象中

流程图

exposedObject = initializeBean(beanName, exposedObject, mbd)

余下的初始化工作

invokeAwareMethods(beanName, bean)
若 bean 实现了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等接口,则向 bean 中注入相关对象 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
实例化前执行后置处理器对应的postProcessBeforeInitialization方法

invokeInitMethods(beanName, wrappedBean, mbd)

  1. 判断是否是InitializingBean的实现,执行接口规定的初始化afterPropertiesSet
  2. 执行invokeCustomInitMethod,方法大致是
    找出所有初始化方法(@Bean initMethod属性指定的方法) mbd.getInitMethodName() 对应去执行

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
执行 bean 初始化后置操作,AOP 会在此处向目标对象中织入切面逻辑

如果是FactoryBean

FactoryBean一直都没怎么用过 所以自己写了demo用下

    @Autowiredprivate Student2 student2;
复制代码

debug一下 查看下执行过程

发现它是在Student2.Class是在populateBean的时候调用processor进行inject时被实例化的,此时发现是FactoryBean就直接被调用了getObject 拿到这个bean 也就是说,一开始被实例化的只有MyFactoryBean这个类,而没有Student2这个类
MyFactoryBean此时beanName=&myFactoryBean

总结

这次Spring ioc源码看了我好几天,收获还是挺大的,也总结

  1. 查看源码前提:是必须要知道怎么用
  2. 如果实在看不懂,可以google找再总结
  3. 有时有些很底层的可以先跳过,先直接到知道必将执行的方法打断点,由后往前看方法栈debug(如FactoryBean这部分)

最后关于Spring总结 主要按着下面四点去看 1)、Spring容器在启动,先保存Bean定义信息

  • xml注册bean
  • 注解注册Bean

2)、Spring容器会在XX的情况下创建Bean

  • 用到这个bean的时候 去创建 *finishBeanFactoryInitialization 统一创建bean

3)、后置处理器 *每一个Bean创建完成 会使用处理器处理

  • AutowiredAnnotationBeanPostProcessor 处理自动注入
  • XXXPostProcessor

4)、事件驱动模型 *ApplicationListener 事件监听 *ApplicationEventMulticaster 事件派发

转载于:https://juejin.im/post/5cb2cc775188251b0477e69b

Spring启动过程——源码分析(finishBeanFactoryInitialization(beanFactory))相关推荐

  1. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  2. Spring Boot 2.x 启动全过程源码分析(全)

    上篇<Spring Boot 2.x 启动全过程源码分析(一)入口类剖析>我们分析了 Spring Boot 入口类 SpringApplication 的源码,并知道了其构造原理,这篇我 ...

  3. Spring Boot 2.x 启动全过程源码分析(上)入口类剖析

    转载自   Spring Boot 2.x 启动全过程源码分析(上)入口类剖析 Spring Boot 的应用教程我们已经分享过很多了,今天来通过源码来分析下它的启动过程,探究下 Spring Boo ...

  4. Spring IOC 容器源码分析

    Spring IOC 容器源码分析 创建时间: 2017-11-15 00:00:00 [TOC] Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring ...

  5. Spring IOC 容器源码分析系列文章导读 1

    1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...

  6. Spring框架—SpringBean源码分析

    原文作者:Javadoop 原文地址:Spring IOC 容器源码分析 在继续往下之前,我们需要先了解 BeanDefinition.我们说 BeanFactory 是 Bean 容器,那么 Bea ...

  7. Spring IOC 容器源码分析 - 余下的初始化工作

    1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bea ...

  8. Spring IOC 容器源码分析 - 填充属性到 bean 原始对象

    1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反 ...

  9. Spring IOC 容器源码分析 - 创建原始 bean 对象

    1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...

  10. Spring IOC 容器源码分析 - 获取单例 bean

    1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...

最新文章

  1. ZBarSDK扫描二维码
  2. mysql删除赋权_mysql 添加用户 删除用户 赋权
  3. 数据库设计三大范式应用实例剖析
  4. 1000道Python题库系列分享
  5. 2018年13个AI趋势 | CB Insights报告
  6. Linux下Ipython安装
  7. Atitit 面向对象  封装的实现原理
  8. web用css做网页实验报告,Web实验报告网页设计与制作
  9. 原生js模仿京东图片放大镜效果
  10. Windows10 地平线4支持PS4手柄有线连接
  11. 怎样清理苹果电脑磁盘空间_Mac空间不足怎么办,快速清理Mac系统垃圾与磁盘|Crucial(英睿达)...
  12. php搜索银行所在支行,多家银行宣布启动社区支行战略但风光不再
  13. 图形验证码空白如何处理
  14. ubuntu16.04无法联网
  15. 词袋模型和空间金字塔模型
  16. java模拟内存溢出并分析_本地模拟内存溢出并分析Dump文件
  17. 计算机桌面图标在地址栏,我的电脑地址栏不见了怎么办
  18. COCO数据集可视化程序(包括bbox和segmentation)
  19. SPOJ - COT Count on a tree [LCA+主席树]【数据结构】
  20. 关于table.rows 基本用法

热门文章

  1. 微信小程序自动定位城市
  2. MoguBlog(蘑菇博客)v5.3发布,前后端分离博客系统
  3. gogs 把用户加入团队
  4. nginx 使用自定义 log_format 以及输出自定义http头
  5. 时空不平坦,能量不守恒。大爆炸时粒子凭空产生的情形
  6. WINDOWS对文件签名,算法如何由sha1改为sha256/sha512
  7. 软件版本的GA、RC的具体含义
  8. Freeswitch视频会议终于成功,及提供解决办法
  9. java.lang.UnsatisfiedLinkError: JNA support (com/sun/jna/android-arm/libjnidispatch.so) not found
  10. 编译OpenJDK12:Target CPU mismatch. We are building for x86_64 but CL is for ; expected x64