简单说说 Bean的生命周期源码

news2024/10/17 5:25:14

在spring中核心进行bean的初始化的方法是AbstractAutowireCapableBeanFactory 类的 doCreateBean 方法,生命周期的全部大致流程都在这里进行了描述

分别是:1 创建实例 ;2 填充属性 3 初始化

//AbstractAutowireCapableBeanFactory 类
//创建bean的过程
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    //如果是单例,先从缓存中进行获取,如果获取的到,则直接使用
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    //如果缓存中没有,则创建bean实例
    if (instanceWrapper == null) {
        //【核心】创建实例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    //获取bean实例
    Object bean = instanceWrapper.getWrappedInstance();
    //获取bean的类型
    Class<?> beanType = instanceWrapper.getWrappedClass();
    //设置一下BeanDefinition中bean最终的目标类型
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    //允许后置处理器修改合并后的bean定义
    //在spring中的bean定义可以通过多种方法,比如说xml、注解,java配置
    //这些配置最终需要进行合并,通过MergedBeanDefinitionPostProcessor对这些合并后的bean进行一步修改增强
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                //执行后置处理器
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            //标记为后置处理已完成
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    //判断是否支持循环依赖(是单例 && 允许循环引用 && 当前bean正在创建中)
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        //这个方法会将当前的实例化完成,初始化未完的对象,存储到 singletonFactories 缓存中去
        //之所以存到的是三级缓存,是因为对象可能是经过aop的,在singletonFactories中存储的是ObjectFactory
        // ObjectFactory是一个函数式接口,如果对象有经过aop会返回aop对象,否则返回原对象
        //singletonFactories 就是我们所说的三级缓存
        //同时,会将beanName 存入 registeredSingletons 列表中,作用是提前曝光,是解决循环袭来的关键
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        //【核心】填充bean的属性
        //1 完成属性的注入,根据bean定义的时候,设置的属性值。
        //2 解析依赖 如果bean依赖其他的bean,则其会递归的去创建其他的bean
        //3 调用BeanPostProcessor,这里主要是执行 InstantiationAwareBeanPostProcessor
        populateBean(beanName, mbd, instanceWrapper);
        //【核心】初始化bean
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }
    //如果提前暴露了单例bean,进行最终处理
    if (earlySingletonExposure) {
        ...
    }

    // Register bean as disposable.
    //注册bean为可销毁的
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

initializeBean 是spring中,对bean进行初始化的核心方法,在该方法中,主要完成的是

1 调用aware接口提供的方法

2 调用BeanPostProcessor的前置方法(比如ApplicationContextAwareProcessor,将ApplicationContext赋值给bean)

3 初始化,执行顺序为,如果继承了InitializingBean,则会去执行afterPropertiesSet方法,然后如果配置了init-method,则会去执行。

4 调用BeanPostProcessor的后置方法(一般aop的增强在这里进行,可以确保bean已经完成初始化)

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            //调用aware接口的方法,这里调用了三个aware 
            // BeanNameAware、BeanClassLoaderAware和 BeanFactoryAware
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        //调用aware接口的方法,这里调用了三个aware 
        // BeanNameAware、BeanClassLoaderAware和 BeanFactoryAware
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //调用BeanPosterProcessor的前置方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //调用初始化方法
        //1 init-method 属性指定的方法
        //2 实现了InitializingBean接口的 afterPropertiesSet方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        调用BeanPosterProcessor的后置方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

其他spring相关博客

简单谈谈Spring 中Aware是什么-CSDN博客

简单说说 Spring 中BeanPostProcessor是什么-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2216815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git push错误failed to push some refs to解决方法

主流解决方法网上全是&#xff0c;例如解决目标仓库和本地仓库的版本冲突&#xff1b;关闭”受保护的仓库“权限。 本文讲述一种 网上几乎没有文章会讲解的一种可能的解决方式&#xff1a; 问题描述&#xff1a; 解决方式&#xff1a; 取消勾选即可

【Cadence27】HDL拷贝工程➕Allegro导出DXF和3D文件STP

【转载】Cadence Design Entry HDL 使用教程 【Cadence01】Cadence PCB Edit相对延迟与绝对延迟的显示问题 【Cadence02】Allegro引脚焊盘Pin设置为透明 【Cadence03】cadence不小心删掉钢网层怎么办&#xff1f; 【Cadence04】一般情况下Allegro PCB设计时的约束规则设置&a…

python之socket网络编程

华子目录 引言什么是socketsocket套接字类型TCP和UDP socket服务端核心组件1.创建socket对象2.绑定地址和端口3.监听连接4.接受连接5.接受client端消息client_sock.revc(1024)6.发送响应给client端6.1client_sock.send()6.2client_sock.sendall() 7.关闭client端连接8.关闭serv…

【初阶数据结构】归并排序 - 分而治之的排序魔法

文章目录 前言1. 什么是归并排序&#xff1f;1.1 归并排序的步骤 2. 归并排序的代码实现2.1 归并排序代码的关键部分讲解2.1.1 利用递归2.1.2 将拆解的数组的元素放到一个临时空间中进行重新排序2.1.3 将在临时空间中排好的数组复制到目标数组中 3. 归并排序的非递归写法 前言 …

未来汽车究竟该是什么样子?

24年10月14日&#xff0c;在中国&#xff08;深圳&#xff09;机器视觉展暨机器视觉技术及工业应用研讨会上&#xff0c;同行者分享了未来智能座舱应该长什么样子。 受此启发&#xff0c;个人觉得当前大多数新能源车都极力想做出电动感&#xff0c;但是布局传统没跳出来&#…

DAY52WEB 攻防-XSS 跨站反射型存储型DOM 型标签闭合输入输出JS 代码解析

#知识点&#xff1a; 1、XSS跨站-输入输出-原理&分类&闭合 2、XSS跨站-分类测试-反射&存储&DOM 演示案例&#xff1a; ➢XSS跨站-输入输出-原理&分类&闭合 ➢XSS跨站-分类测试-反射&存储&DOM #XSS跨站-输入输出-原理&分类&闭合 漏…

安防监控摄像头图传模组,1公里WiFi无线传输方案,监控新科技

在数字化浪潮汹涌的今天&#xff0c;安防监控领域也迎来了技术革新的春风。今天&#xff0c;我们就来聊聊这一领域的产品——摄像头图传模组&#xff0c;以及它如何借助飞睿智能1公里WiFi无线传输技术&#xff0c;为安防监控带来未有的便利与高效。 一、安防监控的新篇章 随着…

基于Java+Springboot+Vue开发的酒店客房预订管理系统

项目简介 该项目是基于JavaSpringbootVue开发的酒店客房预订管理系统&#xff08;前后端分离&#xff09;&#xff0c;这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能&#xff0c;同时锻炼他们的项目设计与开发能力。通过学习基于Java…

【AI学习】Mamba学习(七):HiPPO通用框架介绍

HiPPO这篇论文《HiPPO: Recurrent Memory with Optimal Polynomial Projections》&#xff0c;提出了一个通用框架。 我们再重新看一下论文的摘要&#xff1a; 从连续数据中学习的一个核心问题是&#xff0c;随着更多数据的处理&#xff0c;以增量方式表示累积历史。我们介绍了…

【记录】Windows|Windows 修改字体大全(Windows 桌面、VSCode、浏览器)

【记录】Windows&#xff5c;Windows 修改字体大全&#xff08;Windows 桌面、VSCode、浏览器&#xff09; 前言 最近从学长那里发现了一款非常美观的衡水体字体——Maple Mono SC NF。您可以通过以下链接下载该字体&#xff1a;https://github.com/subframe7536/maple-font/…

【C语言刷力扣】1832.判断句子是否为全字母句

题目&#xff1a; 法一 bool checkIfPangram(char* sentence) {int str[256];memset(str, 0, sizeof(int));for (int i 0; i < strlen(sentence); i) {str[ sentence[i] ];}for (int j a; j < z; j) {if (!str[j]) return false;}return true; } 法二 动态分配 typ…

C++ operator new和operator delete的深入讲解

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 前言 关于operator new和operator delete我们需要明确一个概念&#xff0c;这两个都是…

2024全新UI网址发布页源码带黑夜模式

源码简介 2024全新UI网址发布页源码带黑夜模式&#xff0c;带网站延迟测速&#xff0c;该源码是html源码&#xff0c;可以做个引导页面。 安装教程 纯HTML&#xff0c;直接将压缩包上传网站目录解压即可(或在本地直接打开) 首页截图 源码下载 2024全新UI网址发布页源码带黑…

​​Vision Pro/空间计算小白体系化练手案例:从入门到精通的实战项目指南

引言 随着苹果Vision Pro的发布,空间计算技术正迎来前所未有的发展机遇。对于希望进入这一领域的开发者来说,掌握visionOS及相关工具链是至关重要的第一步。本文将介绍一系列由浅入深的实战项目,旨在帮助初学者系统地学习并实践visionOS开发。这些项目不仅适合个人学习,也…

踩坑日记:线上接口超时问题排查

1.背景: 上线后,功能测试. 进入小程序页面发现很慢,耗时超过5秒,打开skywalking发现大量接口耗时都很高. 2.top命令 服务器top命令查看cpu资源发现占用并不高 3.mysql查看sql运行情况 # 当前运行的所有事务 select * from information_schema.innodb_trx; 1 | …

国内液压一体式潜孔钻机市场相对分散

根据研究团队调研统计&#xff0c;2023年全球液压一体式潜孔钻机市场销售额达到了52亿元&#xff0c;预计2030年将达到90亿元&#xff0c;年复合增长率&#xff08;CAGR&#xff09;为7.1%&#xff08;2024-2030&#xff09;。中国市场在过去几年变化较快&#xff0c;2023年市场…

计算机网络基础(1)

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络基础 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 计算机网…

100. UE5 GAS RPG 显示范围魔法的攻击范围

在这一篇里&#xff0c;我们将制作一个范围魔法&#xff0c;释放魔法时&#xff0c;我们将在鼠标拾取位置绘制一个魔法光圈&#xff0c;用于显示技能释放时攻击的范围&#xff0c;然后再次点击可以释放技能。 创建贴花类 魔法范围标识的光圈&#xff0c;我们采用贴花实现&…

AI 代码工具大揭秘:提高编程效率的必备神器!

近年来&#xff0c;人工智能得到了迅猛的发展&#xff0c;并在各行各业都得到了广泛应用。尤其是近两年来&#xff0c;AI开发工具逐渐成为开发者们的新宠&#xff0c;其中GitHub Copilot更是引发了无限可能性的探索。在本文中&#xff0c;我将向大家介绍一些实用性较高的智能开…

徒步1 -经典贪心

# 问题描述 小明想从A徒步到B&#xff0c;总路程需要M天&#xff0c;路程中为了确保安全&#xff0c;小明每天需要消耗1份食物。 在起点及路程当中&#xff0c;零星分布着N个补给站&#xff0c;可以补充食物&#xff0c;不同补给站的食物价格可能不同。 请问小明若要安全完…