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

环境: spring5.X + idea

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

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

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

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

  // 第一步是完成对象创建所需要的基本数据也就是 beanDefinition
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
// 然后开始创建对象
User user = bf.getBean("user");
// 1. getBean() 进入 AbstractBeanFactory 中的 doGetBean 方法去做创建对象的具体步骤。
protected <T> T doGetBean(String name, ....................... ..) throws BeansException {
String beanName = this.transformedBeanName(name);
// 先去 DefaultSingletonBeanRegistry 中的 singletonObjects 获取对应的bean,
// 因为spring 默认 scope = singleton 单例bean不需要每次都创建
Object sharedInstance = this.getSingleton(beanName);
Object bean;
...........
// scope = Singleton
if(mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
// 开始去创建bean
return this.createBean(beanName, mbd, args);
}
......
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
// scope = Prototype
} else if(mbd.isPrototype()) {
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
// 开始去创建bean
prototypeInstance = this.createBean(beanName, mbd, args);
}
...........
} else {
// 其他情况
...
}
}
// this.createBean(.....) 进入到 AbstractAutowireCapableBeanFactory 中的 createBean方法
protected Object createBean(String beanName...........) throws BeanCreationException {
try {
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
..........
}
  • Spring先实例化对象

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

    填充属性值
    	// 还是刚才的 doCreateBean方法中
    protected Object doCreateBean(String beanName............) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if(mbd.isSingleton()) {
    instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }
    if(instanceWrapper == null) {
    // 这里是 第一步创建对象
    instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }
    Object exposedObject = bean;
    try {
    // 这一步是填充属性
    this.populateBean(beanName, mbd, instanceWrapper);
    exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
    if(var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
    throw (BeanCreationException)var18;
    }
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    }
    }
  • 初始化对象
    	// 还是刚才的 doCreateBean方法中
    protected Object doCreateBean(String beanName............) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if(mbd.isSingleton()) {
    instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }
    if(instanceWrapper == null) {
    // 这里是 第一步创建对象
    instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }
    Object exposedObject = bean;
    try {
    // 这一步是填充属性
    this.populateBean(beanName, mbd, instanceWrapper);
    // 这一步是初始化对象
    exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
    if(var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
    throw (BeanCreationException)var18;
    }
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    }
    }
  • 销毁
    DisposableBeanAdapter implements DisposableBean, Runnable, Serializable{
    public void destroy() {
    //销毁
    }
    }

最后

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

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

干货分享之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. VMware安装最新版CentOS7图文教程

    https://blog.csdn.net/reticent_man/article/details/80732395 https://blog.csdn.net/q2158798/article/d ...

  2. sql case when 多条件小结

    sql case when 多条件 小结 -- 第一种 格式 : 简单Case函数 : -- 格式说明 -- case 列名 -- when 条件值1 then 选择项1 -- when 条件值2 t ...

  3. Jemter请求乱码解决方案

    1:jemeter查看结果树乱码 (1)在jmeter的bin目录下找到jmeter.properties这个文件,添加上 sampleresult.default.encoding=utf-8 (2 ...

  4. Hive——安装以及概述

    一.hive的安装 注意:安装hive的前提要安装好MySQL和Hadoop Hadoop安装:https://www.cnblogs.com/lmandcc/p/15306163.html MySQ ...

  5. Linux如何配置网络ip?

    Linux如何配置网络ip? 1.首先切换至root用户 su root 输入root用户密码 2.借助dhclient工具自动生成一个网络内可用的ip地址 我们可以手动配置对应的网段的ip地址,但是 ...

  6. Vue2.0 基础入门

    前言:" 今生遇汝,何其幸哉:于我蒙昧之时遇到你,于我大雾初透之时爱上你,于我大智初醒之时沉沦你. " 官网: 介绍 - Vue.js (vuejs.org) 指令与修饰符 创建实 ...

  7. mimikatz使用笔记

    一.获取密码# privilege::debug sekurlsa::logonpasswords mimikatz.exe "sekurlsa::debug" "sek ...

  8. VUE -input输入框字母转大写

    示例: 输入自动转--->大写 <input type="text" placeholder="请输入证件号码" maxlength="1 ...

  9. 微信小程序Canvas添加水印字体,通过setGlobalAlpha设置字体透明度。

    微信小程序自带的设置透明度只有setGlobalAlpha,但是CanvasContext.setGlobalAlpha设置透明度,是全局透明,整张图片都透明了.所以直接使用是不行的. 换种思路实现: ...

  10. 峰值利用率80%+,视频云离线转码自研上云TKE实践

    作者 刘兆瑞,腾讯云高级研发工程师,负责腾讯明眸极速高清,画质重生等产品.专注于codec优化,画质增强等技术. 背景和问题 随着流量资费的降低和带宽的增加,视频成为人们获取信息越来越重要的方式,随之 ...