Spring之Bean的初始化 Bean的生命周期 全站式解析

news2025/5/18 17:37:15

目录

导图

步骤

第一步 实例化

第二步 属性赋值

第三步 初始化

aware 接口

BeanPostProcessor 接口

InitializingBean 和 init-method

第四步使用

第五步使用后销毁


描述一下 Bean 的 生命周期

导图

步骤

总体上可以分为五步

  1. 首先是 Bean 的实例化
  2. Bean 在进行实例化后 , 进行属性赋值
  3. 接着初始化 Bean
  4. 使用 Bean
  5. Bean 销毁

第一步 实例化

首先是实例化一个 Bean 对象

主要使用的 createBeanInstance()方法实现

将 bean 挂载到一个包装器上 BeanWrapper

    BeanWrapper instanceWrapper = null;
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }

createBeanInstance()方法 是用来实例化 bean 的

伪代码逻辑

通过反射(无参构造函数)拿到 工厂方法拿到 动态代理...

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 1. 解析bean的class类型
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
    // 2. 检查是否指定了工厂方法
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    
    // 3. 处理有参构造函数
    if (args != null) {
        return autowireConstructor(beanName, mbd, null, args);
    }
    
    // 4. 处理无参构造函数
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, null, args);
    }
    
    // 5. 默认使用无参构造函数实例化
    return instantiateBean(beanName, mbd);
}

第二步 属性赋值

使用 populateBean() 方法 进行赋值

        // 2. 属性赋值
        populateBean(beanName, mbd, instanceWrapper);

我来详细讲一下这个populateBean 方法

我们把 beanname 还有一个刚刚的 beanwapper 包装器传入populateBean() 方法

  1. 前置处理
    • 允许 BeanPostProcessor 干预属性注入流程(如 @Autowired 字段注入)
  1. 属性值准备
    • 获取配置的属性值(XML / 注解)
    • 处理自动装配(byName/byType)
    • 应用 BeanPostProcessor 修改属性值(如 @Value 解析)
  1. 属性注入
    • 解析属性值(处理对其他 bean 的引用)
    • 类型转换(字符串 → 目标类型)
    • 通过 BeanWrapper 完成最终注入
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    // 1. 检查 BeanWrapper 是否为空
    if (bw == null) {
        return;
    }

    // 2. 允许 BeanPostProcessor 在属性注入前修改 bean(如 @Autowired 字段注入)
    boolean continuePopulation = true;
    if (hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            if (processor instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) processor;
                // 例如:AutowiredAnnotationBeanPostProcessor 会在此处理 @Autowired 字段
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continuePopulation = false;
                    break;
                }
            }
        }
    }
    if (!continuePopulation) {
        return;
    }

    // 3. 获取配置的属性值(来自 XML 或注解)
    PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;

    // 4. 处理自动装配(byName/byType)
    int autowireMode = mbd.getResolvedAutowireMode();
    if (autowireMode == RootBeanDefinition.AUTOWIRE_BY_NAME ||
        autowireMode == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        
        // 按名称自动装配:例如 <property name="userService"/>
        if (autowireMode == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        
        // 按类型自动装配:例如 @Autowired UserService userService;
        if (autowireMode == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        
        pvs = newPvs;
    }

    // 5. 应用 BeanPostProcessor 修改属性值(如 @Value 解析)
    if (hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            if (processor instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) processor;
                // 例如:CommonAnnotationBeanPostProcessor 处理 @Resource
                PropertyValues processedPvs = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (processedPvs != null) {
                    pvs = processedPvs;
                }
            }
        }
    }

    // 6. 应用最终的属性值到 bean 实例
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

// 简化版:按名称自动装配
private void autowireByName(String beanName, BeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    // 获取所有未设置值的属性
    String[] propertyNames = getUnsatisfiedPropertyNames(bw);
    
    for (String propertyName : propertyNames) {
        // 如果容器中有同名的 bean,则自动注入
        if (containsBean(propertyName)) {
            Object bean = getBean(propertyName);
            pvs.add(propertyName, bean);
            // 注册依赖关系
            registerDependentBean(propertyName, beanName);
        }
    }
}

// 简化版:按类型自动装配
private void autowireByType(String beanName, BeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    TypeConverter converter = getTypeConverter();
    String[] propertyNames = getUnsatisfiedPropertyNames(bw);
    
    for (String propertyName : propertyNames) {
        try {
            // 获取属性类型
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            Class<?> propertyType = pd.getPropertyType();
            
            // 查找匹配类型的 bean
            Object autowiredValue = resolveDependencyByType(propertyType, beanName);
            if (autowiredValue != null) {
                pvs.add(propertyName, autowiredValue);
            }
        } catch (BeansException ex) {
            throw new BeanCreationException("自动装配失败: " + propertyName, ex);
        }
    }
}

// 简化版:应用属性值
private void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    if (pvs.isEmpty()) {
        return;
    }
    
    TypeConverter converter = getTypeConverter();
    BeanDefinitionValueResolver resolver = new BeanDefinitionValueResolver(
        this, beanName, mbd, converter);
    
    // 解析所有属性值(处理引用、类型转换等)
    List<PropertyValue> resolvedValues = new ArrayList<>();
    for (PropertyValue pv : pvs.getPropertyValues()) {
        String propertyName = pv.getName();
        Object originalValue = pv.getValue();
        
        // 解析可能的 bean 引用(如 ref="userService")
        Object resolvedValue = resolver.resolveValueIfNecessary(pv, originalValue);
        
        // 类型转换(如 String → Integer)
        Object convertedValue = convertIfNecessary(resolvedValue, propertyName, bw, converter);
        
        resolvedValues.add(new PropertyValue(propertyName, convertedValue));
    }
    
    // 应用解析后的属性值到 bean
    try {
        bw.setPropertyValues(new MutablePropertyValues(resolvedValues));
    } catch (BeansException ex) {
        throw new BeanCreationException("设置属性值失败", ex);
    }
}

第三步 初始化

初始化还是比较复杂的

大体上的逻辑

  1. 检查 aware 相关接口设置依赖
  2. BeanPostProcessor 前置处理
  3. 若实现 InitializingBean 接口,调用 afterPropertiesSet() 方法
  4. 若配置自定义的 init-method方法,则执行
  5. BeanPostProceesor 后置处理
// AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 3. 检查 Aware 相关接口并设置相关依赖
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    // 4. BeanPostProcessor 前置处理
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    // 5. 若实现 InitializingBean 接口,调用 afterPropertiesSet() 方法
    // 6. 若配置自定义的 init-method方法,则执行
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }
    // 7. BeanPostProceesor 后置处理
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

aware 接口

注入相关依赖

若 Spring 检测到 bean 实现了 Aware 接口,则会为其注入相应的依赖。所以通过让bean 实现 Aware 接口,则能在 bean 中获得相应的 Spring 容器资源

Spring 中提供的 Aware 接口有:

  1. BeanNameAware:注入当前 bean 对应 beanName;
  2. BeanClassLoaderAware:注入加载当前 bean 的 ClassLoader;
  3. BeanFactoryAware:注入 当前BeanFactory容器 的引用。
// AbstractAutowireCapableBeanFactory.java
private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

以上是针对 BeanFactory 类型的容器,而对于 ApplicationContext 类型的容器,也提供了 Aware 接口,只不过这些 Aware 接口的注入实现,是通过 BeanPostProcessor 的方式注入的,但其作用仍是注入依赖。

  1. EnvironmentAware:注入 Enviroment,一般用于获取配置属性;
  2. EmbeddedValueResolverAware:注入 EmbeddedValueResolver(Spring EL解析器),一般用于参数解析;
  3. ApplicationContextAware(ResourceLoader、ApplicationEventPublisherAware、MessageSourceAware):注入 ApplicationContext 容器本身。
// ApplicationContextAwareProcessor.java
private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
    }

    if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }

    if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
    }

    if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
    }

    if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware)bean).setMessageSource(this.applicationContext);
    }

    if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
    }

}

BeanPostProcessor 接口

BeanPostProcessor 是 Spring 为修改 bean提供的强大扩展点,其可作用于容器中所有 bean,其定义如下:

常用场景有:

  1. 对于标记接口的实现类,进行自定义处理。例如3.1节中所说的ApplicationContextAwareProcessor,为其注入相应依赖;再举个例子,自定义对实现解密接口的类,将对其属性进行解密处理;
  2. 为当前对象提供代理实现。例如 Spring AOP 功能,生成对象的代理类,然后返回。
// AbstractAutoProxyCreator.java
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // 返回代理类
        return proxy;
    }

    return null;
}

InitializingBean 和 init-method

初始化拓展点

InitializingBean 接口

public interface InitializingBean {
	void afterPropertiesSet() throws Exception;
}

指定 init-method 方法,指定初始化方法:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="demo" class="com.chaycao.Demo" init-method="init()"/>
    
</beans>

第四步使用

第五步使用后销毁

类似于 InitializingBean() 和 init-method()

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

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

相关文章

FreeCAD源码分析: Transaction实现原理

本文阐述FreeCAD中Transaction的实现原理。 注1&#xff1a;限于研究水平&#xff0c;分析难免不当&#xff0c;欢迎批评指正。 注2&#xff1a;文章内容会不定期更新。 一、概念 Ref. from What is a Transaction? A transaction is a group of operations that have the f…

flutter缓存网络视频到本地,可离线观看

记录一下解决问题的过程&#xff0c;希望自己以后可以参考看看&#xff0c;解决更多的问题。 需求&#xff1a;flutter 缓存网络视频文件&#xff0c;可离线观看。 解决&#xff1a; 1&#xff0c;flutter APP视频播放组件调整&#xff1b; 2&#xff0c;找到视频播放组件&a…

Kotlin 中 infix 关键字的原理和使用场景

在 Kotlin 中&#xff0c;使用 infix 关键字修饰的函数称为中缀函数&#xff0c;使用是可以省略 . 和 ()&#xff0c;允许以更自然&#xff08;类似自然语言&#xff09;的语法调用函数&#xff0c;这种特性可以使代码更具可读性。 1 infix 的原理 中缀函数必须满足以下条件&…

c++从入门到精通(五)--异常处理,命名空间,多继承与虚继承

异常处理 栈展开过程&#xff1a; 栈展开过程沿着嵌套函数的调用链不断查找&#xff0c;直到找到了与异常匹配的catch子句为止&#xff1b;也可能一直没找到匹配的catch&#xff0c;则退出主函数后查找过程终止。栈展开过程中的对象被自动销毁。 在栈展开的过程中&#xff0c…

gcc/g++常用参数

1.介绍 gcc用于编译c语言&#xff0c;g用于编译c 源代码生成可执行文件过程&#xff0c;预处理-编译-汇编-链接。https://zhuanlan.zhihu.com/p/476697014 2.常用参数说明 2.1编译过程控制 参数作用-oOutput&#xff0c;指定输出名字-cCompile&#xff0c;编译源文件生成对…

nginx配置之负载均衡

版权声明&#xff1a;原创作品&#xff0c;请勿转载&#xff01; 1.实验环境准备 准备3台linux服务器&#xff08;ubuntu和centos均可&#xff0c;本文使用centos7.9&#xff09;&#xff0c;两台web和一台负载均衡服务器&#xff0c;均安装nginx服务 主机名IP软件lb0110.0.0…

去年开发一款鸿蒙Next Os的window工具箱

持拖载多个鸿蒙应用 批量签名安装 运行 http://dl.lozn.top/lozn/HarmonySignAndFileManagerTool_2024-11-26.zip 同类型安卓工具箱以及其他软件下载地址汇总 http://dl.lozn.top/lozn/ 怎么个玩法呢&#xff0c;比如要启动某app, 拖载识别到包名 点启动他能主动读取包名 然后…

uniapp|实现获取手机摄像头权限,调用相机拍照实现人脸识别相似度对比,拍照保存至相册,多端兼容(APP/微信小程序)

基于uniapp以及微信小程序实现移动端人脸识别相似度对比,实现摄像头、相册权限获取、相机模块交互、第三方识别集成等功能,附完整代码。 目录 核心功能实现流程摄像头与相册权限申请权限拒绝后的引导策略摄像头调用拍照事件处理人脸识别集成图片预处理(Base64编码/压缩)调用…

JavaScript【7】BOM模型

1.概述&#xff1a; BOM&#xff08;Browser Object Model&#xff0c;浏览器对象模型&#xff09;是 JavaScript 中的一个重要概念&#xff0c;它提供了一系列对象来访问和操作浏览器的功能和信息。与 DOM&#xff08;Document Object Model&#xff09;主要关注文档结构不同&…

[强化学习的数学原理—赵世钰老师]学习笔记02-贝尔曼方程

本人为强化学习小白&#xff0c;为了在后续科研的过程中能够较好的结合强化学习来做相关研究&#xff0c;特意买了西湖大学赵世钰老师撰写的《强化学习数学原理》中文版这本书&#xff0c;并结合赵老师的讲解视频来学习和更深刻的理解强化学习相关概念&#xff0c;知识和算法技…

深入理解构造函数,析构函数

目录 1.引言 2.构造函数 1.概念 2.特性 3.析构函数 1.概念 2.特性 1.引言 如果一个类中什么都没有&#xff0c;叫作空类. class A {}; 那么我们这个类中真的是什么都没有吗?其实不是,如果我们类当中上面都不写.编译器会生成6个默认的成员函数。 默认成员函数:用户没有显…

Day 16

目录 1.JZ79 判断是不是平衡二叉树1.1 解析1.2 代码 2.DP10 最大子矩阵2.1 解析2.2 代码 1.JZ79 判断是不是平衡二叉树 JZ79 判断是不是平衡二叉树 dfs 1.1 解析 1.2 代码 /*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(in…

摄影构图小节

1、三分构图法 三分构图法即将画面横竖各分为三份&#xff0c;即九宫格形式。 将画面用两条竖线和两条横线分割&#xff0c;就如同是书写中文的【井】字。这样就可以得到4个交叉点&#xff0c;然后再将需要表现的重点放置在4个交叉点中的一个附近即可。 拍摄自然风光时&#xf…

DAY 28 类的定义和方法

知识点回顾&#xff1a; 类的定义pass占位语句类的初始化方法类的普通方法类的继承&#xff1a;属性的继承、方法的继承 比如def、class这些定义的关键词后&#xff0c;必须有一个有占据缩进位置的代码块。 还有下面这些依赖缩进的语句&#xff0c;都可以用pass语句来占位 x 1…

RAG数据处理:PDF/HTML

RAG而言用户输入的数据通常是各种各样文档&#xff0c;本文主要采用langchain实现PDF/HTML文档的处理方法 PDF文档解析 PDF文档很常见格式&#xff0c;但内部结构常常较复杂&#xff1a; 复杂的版式布局多样的元素&#xff08;段落、表格、公式、图片等&#xff09;文本流无…

机器学习 day04

文章目录 前言一、线性回归的基本概念二、损失函数三、最小二乘法 前言 通过今天的学习&#xff0c;我掌握了机器学习中的线性回归的相关基本概念&#xff0c;包括损失函数的概念&#xff0c;最小二乘法的理论与算法实现。 一、线性回归的基本概念 要理解什么是线性回归&…

蓝牙耳机什么牌子好?倍思值得冲不?

最近总被问“蓝牙耳机什么牌子好”&#xff0c;作为踩过无数坑的资深耳机党&#xff0c;必须安利刚入手的倍思M2s Pro主动降噪蓝牙耳机&#xff01;降噪、音质、颜值全都在线&#xff0c;性价比直接拉满。 -52dB降噪&#xff0c;通勤摸鱼神器 第一次开降噪就被惊到&#xff01…

机器学习-人与机器生数据的区分模型测试-数据处理 - 续

这里继续 机器学习-人与机器生数据的区分模型测试-数据处理1的内容 查看数据 中1的情况 #查看数据1的分布情况 one_ratio_list [] for col in data.columns:if col city or col target or col city2: # 跳过第一列continueelse:one_ratio data[col].mean() # 计算1值占…

ESP系列单片机选择指南:结合实际场景的最优选择方案

前言 在物联网(IoT)快速发展的今天&#xff0c;ESP系列单片机凭借其优异的无线连接能力和丰富的功能特性&#xff0c;已成为智能家居、智慧农业、工业自动化等领域的首选方案。本文将深入分析各款ESP芯片的特点&#xff0c;结合典型应用场景&#xff0c;帮助开发者做出最优选择…

特斯拉虚拟电厂:能源互联网时代的分布式革命

在双碳目标与能源转型的双重驱动下&#xff0c;特斯拉虚拟电厂&#xff08;Virtual Power Plant, VPP&#xff09;通过数字孪生技术与能源系统的深度融合&#xff0c;重构了传统电力系统的运行范式。本文从系统架构、工程实践、技术挑战三个维度&#xff0c;深度解析这一颠覆性…