首页 > 编程语言 >简单说说 Bean的生命周期源码

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

时间:2024-10-20 13:46:04浏览次数:10  
标签:生命周期 mbd beanName bean BeanCreationException Bean 源码 ex null

在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 中Aware是什么-CSDN博客

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

简单说说 spring 是如何处理循环依赖问题的(源码解析)-CSDN博客

简单说说 spring构造器循环依赖 为什么无法解决(源码解析)-CSDN博客

简单说说 spring是如何实现AOP的(源码分析)-CSDN博客

标签:生命周期,mbd,beanName,bean,BeanCreationException,Bean,源码,ex,null
From: https://blog.csdn.net/sjdxx/article/details/142989850

相关文章

  • Pbootcms模板源码如何做好防护
    为了确保PBootCMS模板的安全性和稳定性,除了基本的上传和解压操作外,还需要进行一系列的安全防护措施。以下是一些关键步骤,帮助您更好地保护PBootCMS网站:1.升级到最新版重要性: 确保使用最新版本的PBootCMS可以获得最新的安全补丁和功能改进。步骤:登录PBootCMS官方网......
  • 仓储管理系统-贵金属(源码+文档+部署+讲解)
    仓储管理系统-贵金属、智能仓储管理平台、库存优化控制系统、仓库自动化管理系统、库存智能调配系统、仓储资源规划系统、智能库存监控系统、仓库作业执行系统、库存管理与分析系统、仓库管理智能平台、库存流转跟踪系统、智能供应链管理平台供应商本文将深入解析“仓储管理系统-贵......
  • (开题报告)django+vue酒店管理系统论文+源码
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景关于酒店管理系统的研究,现有研究主要以传统的开发技术为主,专门针对Django+Vue技术栈构建的酒店管理系统研究较少。在国内外,酒店管理......
  • SpringBoot微信小程序网上图书商城销售系统设计与实现计算机毕业设计源码作品和开题报
     博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育、辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩,提供核心代码讲解,答辩指导。项目配有对应开发......
  • 基于SpringBoot的甜品店管理系统(源码+LW+调试文档+讲解)
    一、背景介绍在现代社会,甜品店越来越受到人们的喜爱,成为人们休闲、聚会的好去处。然而,传统的甜品店管理方式往往存在效率低下、信息不透明、服务质量难以保证等问题。为了提高甜品店的管理水平和服务质量,开发一个基于SpringBoot+Vue的Web甜品店管理系统具有重要的现......
  • 基于微信小程序的社区订餐系统(源码+LW+调试文档+讲解)
    一、背景介绍随着生活节奏的加快和人们对便捷生活的追求,社区订餐服务的需求日益增长。传统的订餐方式存在诸多不便,如电话订餐容易出错、沟通效率低,线下订餐需要花费较多时间和精力。为了满足社区居民的订餐需求,提高订餐效率和服务质量,开发基于SpringBoot+Vue的X社区......
  • (附源码)基于python的旅游大数据系统的设计与实现-计算机毕设 26553
    基于python的旅游大数据系统的设计与实现目 录1绪论1.1选题背景和意义1.2国内外研究现状1.3论文结构与章节安排1.4开发技术1.4.1MVVM模式介绍1.4.2Django框架1.4.3Vue.js主要功能2 系统分析2.1可行性分析2.1.1技术可行性分析2.1.2 操作可......
  • springboot基于java的OA管理系统(源码+文档+调试+vue+前后端分离)
    收藏关注不迷路!!......
  • SpringBoot + Activiti工作流项目示例(源码)
    前言activiti工作流引擎项目,企业erp、oa、hr、crm等企事业办公系统轻松落地,一套完整并且实际运用在多套项目中的案例,满足日常业务流程审批需求。一、项目形式springboot+vue+activiti集成了activiti在线编辑器,流行的前后端分离部署开发模式,快速开发平台,可插拔工作流服务。工......
  • tauri2.0-admin-vue3+element-plus客户端后台管理系统-源码版
    基于Tauriv2+vue3+ElementPlus+Echarts首款重磅桌面端后台管理系统Exe解决方案Tauri2Vue3Admin,正式完结了。趁着周末,录制了一个源码版演示视频。【源码版】tauri2.0+vite5+element-plus中后台管理系统解决方案技术栈编码器:vscode技术框架:tauri2.0+vite5.4.8+vue3.5......