Spring启动过程——源码分析(finishBeanFactoryInitialization(beanFactory))
前言
此篇是补充上篇未分析完的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)
- 判断是否是InitializingBean的实现,执行接口规定的初始化afterPropertiesSet
- 执行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源码看了我好几天,收获还是挺大的,也总结
- 查看源码前提:是必须要知道怎么用
- 如果实在看不懂,可以google找再总结
- 有时有些很底层的可以先跳过,先直接到知道必将执行的方法打断点,由后往前看方法栈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))相关推荐
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...
- Spring Boot 2.x 启动全过程源码分析(全)
上篇<Spring Boot 2.x 启动全过程源码分析(一)入口类剖析>我们分析了 Spring Boot 入口类 SpringApplication 的源码,并知道了其构造原理,这篇我 ...
- Spring Boot 2.x 启动全过程源码分析(上)入口类剖析
转载自 Spring Boot 2.x 启动全过程源码分析(上)入口类剖析 Spring Boot 的应用教程我们已经分享过很多了,今天来通过源码来分析下它的启动过程,探究下 Spring Boo ...
- Spring IOC 容器源码分析
Spring IOC 容器源码分析 创建时间: 2017-11-15 00:00:00 [TOC] Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring ...
- Spring IOC 容器源码分析系列文章导读 1
1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...
- Spring框架—SpringBean源码分析
原文作者:Javadoop 原文地址:Spring IOC 容器源码分析 在继续往下之前,我们需要先了解 BeanDefinition.我们说 BeanFactory 是 Bean 容器,那么 Bea ...
- Spring IOC 容器源码分析 - 余下的初始化工作
1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bea ...
- Spring IOC 容器源码分析 - 填充属性到 bean 原始对象
1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反 ...
- Spring IOC 容器源码分析 - 创建原始 bean 对象
1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...
- Spring IOC 容器源码分析 - 获取单例 bean
1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...
最新文章
- ZBarSDK扫描二维码
- mysql删除赋权_mysql 添加用户 删除用户 赋权
- 数据库设计三大范式应用实例剖析
- 1000道Python题库系列分享
- 2018年13个AI趋势 | CB Insights报告
- Linux下Ipython安装
- Atitit 面向对象 封装的实现原理
- web用css做网页实验报告,Web实验报告网页设计与制作
- 原生js模仿京东图片放大镜效果
- Windows10 地平线4支持PS4手柄有线连接
- 怎样清理苹果电脑磁盘空间_Mac空间不足怎么办,快速清理Mac系统垃圾与磁盘|Crucial(英睿达)...
- php搜索银行所在支行,多家银行宣布启动社区支行战略但风光不再
- 图形验证码空白如何处理
- ubuntu16.04无法联网
- 词袋模型和空间金字塔模型
- java模拟内存溢出并分析_本地模拟内存溢出并分析Dump文件
- 计算机桌面图标在地址栏,我的电脑地址栏不见了怎么办
- COCO数据集可视化程序(包括bbox和segmentation)
- SPOJ - COT Count on a tree [LCA+主席树]【数据结构】
- 关于table.rows 基本用法
热门文章
- 微信小程序自动定位城市
- MoguBlog(蘑菇博客)v5.3发布,前后端分离博客系统
- gogs 把用户加入团队
- nginx 使用自定义 log_format 以及输出自定义http头
- 时空不平坦,能量不守恒。大爆炸时粒子凭空产生的情形
- WINDOWS对文件签名,算法如何由sha1改为sha256/sha512
- 软件版本的GA、RC的具体含义
- Freeswitch视频会议终于成功,及提供解决办法
- java.lang.UnsatisfiedLinkError: JNA support (com/sun/jna/android-arm/libjnidispatch.so) not found
- 编译OpenJDK12:Target CPU mismatch. We are building for x86_64 but CL is for ; expected x64