记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新。欢迎大家指正!

  1. 环境: spring5.X + idea

之前分析了Spring读取xml文件的所有信息封装成beanDefinition,并存到了beanDefinitionMap中以便我们后续使用。

传送门Spring源码分析01-(xml解析)

今天学习spring容器创建对象的整个过程,或者叫对象的生命周期

Spring创建对象的过程(基本数据beanDefinition)

  1. // 第一步是完成对象创建所需要的基本数据也就是 beanDefinition
  2. BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
  3. // 然后开始创建对象
  4. User user = bf.getBean("user");
  5. // 1. getBean() 进入 AbstractBeanFactory 中的 doGetBean 方法去做创建对象的具体步骤。
  6. protected <T> T doGetBean(String name, ....................... ..) throws BeansException {
  7. String beanName = this.transformedBeanName(name);
  8. // 先去 DefaultSingletonBeanRegistry 中的 singletonObjects 获取对应的bean,
  9. // 因为spring 默认 scope = singleton 单例bean不需要每次都创建
  10. Object sharedInstance = this.getSingleton(beanName);
  11. Object bean;
  12. ...........
  13. // scope = Singleton
  14. if(mbd.isSingleton()) {
  15. sharedInstance = this.getSingleton(beanName, () -> {
  16. try {
  17. // 开始去创建bean
  18. return this.createBean(beanName, mbd, args);
  19. }
  20. ......
  21. });
  22. bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  23. // scope = Prototype
  24. } else if(mbd.isPrototype()) {
  25. var11 = null;
  26. Object prototypeInstance;
  27. try {
  28. this.beforePrototypeCreation(beanName);
  29. // 开始去创建bean
  30. prototypeInstance = this.createBean(beanName, mbd, args);
  31. }
  32. ...........
  33. } else {
  34. // 其他情况
  35. ...
  36. }
  37. }
  38. // this.createBean(.....) 进入到 AbstractAutowireCapableBeanFactory 中的 createBean方法
  39. protected Object createBean(String beanName...........) throws BeanCreationException {
  40. try {
  41. beanInstance = this.doCreateBean(beanName, mbdToUse, args);
  42. if(this.logger.isDebugEnabled()) {
  43. this.logger.debug("Finished creating instance of bean '" + beanName + "'");
  44. }
  45. return beanInstance;
  46. }
  47. ..........
  48. }
  • Spring先实例化对象

    dodoCreateBean 方法就是整个创建对象的核心方法
    1. protected Object doCreateBean(String beanName............) throws BeanCreationException {
    2. BeanWrapper instanceWrapper = null;
    3. if(mbd.isSingleton()) {
    4. instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    5. }
    6. if(instanceWrapper == null) {
    7. // 这里是 第一步创建对象
    8. instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    9. }
    10. }
  • 设置对象中的属性值

    填充属性值
    1. // 还是刚才的 doCreateBean方法中
    2. protected Object doCreateBean(String beanName............) throws BeanCreationException {
    3. BeanWrapper instanceWrapper = null;
    4. if(mbd.isSingleton()) {
    5. instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    6. }
    7. if(instanceWrapper == null) {
    8. // 这里是 第一步创建对象
    9. instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    10. }
    11. Object exposedObject = bean;
    12. try {
    13. // 这一步是填充属性
    14. this.populateBean(beanName, mbd, instanceWrapper);
    15. exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    16. } catch (Throwable var18) {
    17. if(var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
    18. throw (BeanCreationException)var18;
    19. }
    20. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    21. }
    22. }
  • 初始化对象
    1. // 还是刚才的 doCreateBean方法中
    2. protected Object doCreateBean(String beanName............) throws BeanCreationException {
    3. BeanWrapper instanceWrapper = null;
    4. if(mbd.isSingleton()) {
    5. instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    6. }
    7. if(instanceWrapper == null) {
    8. // 这里是 第一步创建对象
    9. instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    10. }
    11. Object exposedObject = bean;
    12. try {
    13. // 这一步是填充属性
    14. this.populateBean(beanName, mbd, instanceWrapper);
    15. // 这一步是初始化对象
    16. exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    17. } catch (Throwable var18) {
    18. if(var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
    19. throw (BeanCreationException)var18;
    20. }
    21. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    22. }
    23. }
  • 销毁
    1. DisposableBeanAdapter implements DisposableBean, Runnable, Serializable{
    2. public void destroy() {
    3. //销毁
    4. }
    5. }

最后

感谢您的阅读,有什么意见和问题欢迎评论区留言!书写不易!

觉得文章对你有帮助记得给我点个赞,欢迎大家关注和转发文章!

干货分享之spring框架源码分析02-(对象创建or生命周期)的更多相关文章

  1. 干货分享之Spring框架源码解析01-(xml配置解析)

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea Spring 是一个工厂,是一个负责对象的创建和维护的工厂.它给我 ...

  2. Spring AMQP 源码分析 02 - CachingConnectionFactory

    ### 准备 ## 目标 了解 CachingConnectionFactory 在默认缓存模式下的工作原理   ## 前置知识   <Spring AMQP 源码分析 01 - Impatie ...

  3. 设计模式(五)——原型模式(加Spring框架源码分析)

    原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...

  4. Linux进程调度与源码分析(二)——进程生命周期与task_struct进程结构体

    1.进程生命周期 Linux操作系统属于多任务操作系统,系统中的每个进程能够分时复用CPU时间片,通过有效的进程调度策略实现多任务并行执行.而进程在被CPU调度运行,等待CPU资源分配以及等待外部事件 ...

  5. Tomcat源码分析 | 一文详解生命周期机制Lifecycle

    目录 什么是Lifecycle? Lifecycle方法 LifecycleBase 增加.删除和获取监听器 init() start() stop() destroy() 模板方法 总结 前言 To ...

  6. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  7. Android Small插件化框架源码分析

    Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...

  8. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  9. Spring AOP 源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

随机推荐

  1. 用Python做了个奇奇怪怪的打篮球游戏

    一.前言 准备编写一个篮球游戏,运动员带球跑,跳起投篮.在每帧图片中包括运动员和篮球,使用多帧图片,实现运动员运球跑动的效果. 运动员运球跑动作每帧图形的宽和高可能不同,例如,跨一大步,和两腿并拢,其 ...

  2. Jmeter系列(19)- 常用配置文件

    JMeter.properties :跟Jmeter配置相关的配置信息都在这边,比如:Jmeter GUI页面的语言.日志级别设置等 User.properties:用户自定义相关的所有变量,会复写J ...

  3. python刷题第四周

    本周有所收获的题目: 第一题: 第4章-17 水仙花数(20 分) (20 分) 水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身. 例如:153=1×1×1+5×5×5 ...

  4. FormData上传文件 带进度条

    * jQuery ajax  FormData 上传文件 template $.ajax({ url: url, type: 'POST', data: new FormData(form), dat ...

  5. JavaScript 获取html元素

    1.通过ID获取: document.getElementById("idname"); 2.通过class.tagname获取: var wcyclass = document. ...

  6. Kronecker product

    Kronecker product 的基本运算 结合律 \begin{equation} \mathrm{A} \otimes (\mathrm{B + C}) = \mathrm{A} \otime ...

  7. 小白自制Linux开发板 三. Linux内核与文件系统移植

    上一篇完成了uboot的移植,但是想要愉快的在开发板上玩耍还需要移植Linux内核和文件系统. 1.Linux内核 事实上对于F1C100S/F1C200S,Linux官方源码已经对licheepi ...

  8. 移动端多个DIV简单拖拽功能

    移动端多个DIV简单拖拽功能. 这个demo与之前写的一个例子差不了多少,只是这个多了一层遍历而已. <!DOCTYPE html> <html lang="en" ...

  9. 利用PATH环境变量 - 提升linux权限~👻

    利用PATH提升linux权限 参考地址:https://www.hackingarticles.in/linux-privilege-escalation-using-path-variable/ ...

  10. 洛谷3809 SA模板 后缀数组学习笔记(复习)

    其实SA这个东西很久之前就听过qwq 但是基本已经忘的差不多了 嘤嘤嘤 QWQ感觉自己不是很理解啊 所以写不出来那种博客 QWQ只能安利一些别人的博客了 小老板 真的是讲的非常好 不要在意名字 orz ...