news 2026/4/16 16:15:04

Spring Bean生命周期- BeanDefinition 加载与 BeanFactoryPostProcessor BeanPostProcessor

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Bean生命周期- BeanDefinition 加载与 BeanFactoryPostProcessor BeanPostProcessor

使用细节

  1. 默认是单例singleton,在启动容器时,默认就会创建,并放入到singletonObjects集合中存储实例
  2. 当 设置为多实例机制后,该bean是在getBean()时才创建
  3. 如果是单例singleton,同时希望在getBean时才创建,可以 指定懒加载 lazy-init=“true” (注意默认是false)
  4. 通常情况下, lazy-init 就使用默认值false ,在开发看来,用空间换时间是值得的,除非有特殊的要求.
  5. 如果scope=“prototype” 这时你的 lazy-init 属性的值不管是 true,还是false 都是在getBean时候,才创建对象.

BeanDefinition 与 singletonObjects 的区别

BeanDefinition

  • 存储内容: 存储 bean 的元数据信息(配置信息)
  • 包含内容: bean 的类名、作用域(scope)、属性值、依赖关系、初始化方法、销毁方法等
  • 创建时机: Spring 容器启动时,解析 XML/注解配置后创建
  • 存储位置: 保存在 BeanFactory/ApplicationContext 中,作为创建 bean 实例的模板

singletonObjects

  • 存储内容: 存储单例 bean 的实际实例对象
  • 包含内容: 已经完成实例化、属性注入、初始化的 bean 对象
  • 创建时机: 单例 bean 实例化后(默认启动时,懒加载则第一次 getBean 时)
  • 存储位置: 作为单例缓存,避免重复创建相同实例
  • 非单例 bean 的处理:非单例 bean(如 prototype 作用域)不会被放入 singletonObjects

不同作用域的 bean 存储方式

  1. singleton(单例): 实例放入singletonObjects缓存,重复使用
  2. prototype(原型/多实例): 每次调用getBean()都创建新实例,不缓存,使用后由调用者负责销毁
  3. request(请求): 每个 HTTP 请求创建新实例,请求结束后销毁(仅 Web 环境)
  4. session(会话): 每个 HTTP 会话创建新实例,会话结束后销毁(仅 Web 环境)
  5. application(应用): 每个 ServletContext 创建新实例,应用停止后销毁(仅 Web 环境)

结论: 只有singleton作用域的 bean 会被放入singletonObjects集合,其他作用域的 bean 不会被缓存。

Bean 的生命周期

生命周期概述

Spring Bean 的生命周期是指从 Bean 被创建、初始化、使用到最终销毁的完整过程。Spring 容器负责管理 Bean 的整个生命周期,确保 Bean 在合适的时机完成相应的操作。

详细阶段说明

  1. 根据 xml 配置文件或注解配置, Spring 容器会解析 Bean 定义,并创建一个 BeanDefinition 对象, 该对象包含了 Bean 的元数据信息(类名,作用域,属性值,依赖关系等)
  2. 执行 BeanFactoryPostProcessor: 在所有 BeanDefinition 加载完成后,Bean 实例化之前,Spring 容器会调用所有实现了 BeanFactoryPostProcessor 接口的类的postProcessBeanFactory方法。这些方法可以修改 BeanDefinition 的元数据信息(如属性值、作用域等)
  3. 通过反射机制,根据 BeanDefinition 中的类名,调用对应的构造函数,创建 Bean 的实例.
  4. 属性注入 (DI) : Spring 容器会根据 BeanDefinition 中的依赖关系,将对应的 Bean 实例注入到目标 Bean 的属性中.
  5. 初始化 : 调用 Bean 的初始化方法(如实现 InitializingBean 接口的 afterPropertiesSet 方法,或指定的 init-method 方法)
  6. 通过getBean()方法获取Bean实例时,Spring容器会返回该Bean的实例.
  7. 销毁 : 当 Bean 实例不再需要时,Spring 容器会调用 Bean 的销毁方法(如实现 DisposableBean 接口的 destroy 方法,或指定的 destroy-method 方法)
1. BeanDefinition 加载与 BeanFactoryPostProcessor 执行
  • 时机: Spring 容器启动时,所有 BeanDefinition 加载完成后,Bean 实例化之前
  • 操作:
    • Spring 容器解析 XML/注解配置,创建所有 BeanDefinition 对象
    • 调用所有实现了BeanFactoryPostProcessor接口的类的postProcessBeanFactory方法
  • 作用:
    • 可以修改 BeanDefinition 的元数据信息(如属性值、作用域、初始化方法等)
    • 典型应用:PropertyPlaceholderConfigurer(处理 ${} 占位符)、CustomScopeConfigurer(注册自定义作用域)
  • 执行特点: 在所有 Bean 实例化之前执行,且只执行一次
2. 实例化(Instantiation)
  • 时机: Spring 容器根据 BeanDefinition 创建 Bean 实例
  • 操作: 调用 Bean 的构造函数创建对象
  • 结果: 获得一个原始的 Bean 实例(尚未设置任何属性)
3. 属性注入(Populate)
  • 时机: 实例化完成后
  • 操作: 根据配置(XML/注解)将依赖注入到 Bean 的属性中
  • 实现: 调用 setter 方法或通过构造函数注入依赖
  • 这里的"bean"指: 刚刚完成实例化阶段(通过构造函数创建)的原始 Bean 实例。此时它已经是一个 Java 对象,但尚未设置任何属性值,处于"原始状态"。Spring 容器会将配置中定义的属性值、依赖对象等注入到这个原始实例中,使其成为一个完整可用的 Bean。

例如:当实例化 User 类获得一个 user 对象后,此时 user.name 可能为 null(默认值),属性注入阶段会将配置的 name 值注入到 user 对象中。

4. 初始化前(Before Initialization)
  • 时机: 属性注入完成后
  • 操作: 调用 BeanPostProcessor 的postProcessBeforeInitialization方法
  • 作用: 可以在 Bean 初始化前对其进行增强处理
5. 初始化(Initialization)
  • 时机: 初始化前阶段完成后
  • 操作: 执行自定义的初始化逻辑
  • 实现方式:
    • 实现InitializingBean接口的afterPropertiesSet()方法
    • 在配置中指定init-method属性
    • 使用@PostConstruct注解标记初始化方法
6. 初始化后(After Initialization)
  • 时机: 初始化完成后
  • 操作: 调用 BeanPostProcessor 的postProcessAfterInitialization方法
  • 作用: 可以在 Bean 初始化后进行代理创建或其他增强处理
7. 加入 IoC 容器(Add to IoC Container)
  • 时机: 初始化后阶段完成后(仅针对 singleton 作用域)
  • 操作: Spring 容器将完全初始化的单例 Bean 放入singletonObjects缓存中
  • 作用: 后续调用getBean()时直接从缓存返回,避免重复创建
  • 非单例 Bean 的处理: prototype、request、session、application 等作用域的 Bean不会被加入 singletonObjects 缓存
8. 使用阶段(In Use)
  • 时机: Bean 完全初始化后(单例 Bean 已加入容器缓存)
  • 操作: Bean 可以被应用程序使用(通过getBean()获取)
  • 特点:
    • 单例 Bean:从singletonObjects缓存获取,重复使用
    • 原型 Bean:每次调用getBean()都创建新实例,使用后由调用者负责管理
    • 其他作用域:根据各自作用域规则创建和管理
9. 销毁前(Before Destruction)
  • 时机: 容器关闭前(仅单例 Bean)
  • 操作: 执行自定义的销毁逻辑
  • 实现方式:
    • 实现DisposableBean接口的destroy()方法
    • 在配置中指定destroy-method属性
    • 使用@PreDestroy注解标记销毁方法
10. 销毁(Destruction)
  • 时机: 销毁前阶段完成后
  • 操作: 释放 Bean 占用的资源
  • 注意: 仅单例 Bean 会被容器管理销毁,原型 Bean 由调用者负责销毁

生命周期回调方法示例

publicclassUser{privateStringname;// 构造函数(实例化阶段调用)publicUser(){System.out.println("1. User 构造函数被调用(实例化)");}// setter 方法(属性注入阶段调用)publicvoidsetName(Stringname){this.name=name;System.out.println("2. setName 被调用(属性注入)");}// InitializingBean 接口方法(初始化阶段调用)@OverridepublicvoidafterPropertiesSet(){System.out.println("3. afterPropertiesSet 被调用(InitializingBean 接口)");}// 自定义初始化方法(配置 init-method 指定)publicvoidinit(){System.out.println("4. init 方法被调用(自定义初始化)");}// 业务方法(使用阶段调用)publicvoidsayHello(){System.out.println("5. sayHello 方法被调用(使用中)");}// DisposableBean 接口方法(销毁阶段调用)@Overridepublicvoiddestroy(){System.out.println("6. destroy 方法被调用(DisposableBean 接口)");}// 自定义销毁方法(配置 destroy-method 指定)publicvoidcleanup(){System.out.println("7. cleanup 方法被调用(自定义销毁)");}}

不同作用域对生命周期的影响

作用域实例化时机初始化时机销毁时机容器管理销毁
singleton容器启动(默认)/第一次 getBean实例化后立即初始化容器关闭前
prototype每次 getBean实例化后立即初始化调用者负责销毁
request每个 HTTP 请求开始实例化后立即初始化HTTP 请求结束是(Web环境)
session每个 HTTP 会话开始实例化后立即初始化HTTP 会话结束是(Web环境)
application应用启动实例化后立即初始化应用停止是(Web环境)

关系说明

  1. Spring 先读取配置创建BeanDefinition(元数据)
  2. 然后根据BeanDefinition的配置创建实际的 bean 实例
  3. 单例实例创建完成后,会被放入singletonObjects缓存中
  4. 后续调用getBean()获取单例时,直接从缓存返回,不再重新创建

因此,“存储到实体类中 BeanDefinition” 和 “放入到 singletonObjects 集合” 描述的是 Spring 管理 bean 的不同阶段

  • BeanDefinition 是配置模板
  • singletonObjects 是实例缓存
    两者都是正确的,只是描述了 bean 生命周期中的不同环节。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 9:23:53

Redisson Docker环境DNSMonitor日志优化终极方案

Redisson Docker环境DNSMonitor日志优化终极方案 【免费下载链接】redisson Redisson - Easy Redis Java client with features of In-Memory Data Grid. Sync/Async/RxJava/Reactive API. Over 50 Redis based Java objects and services: Set, Multimap, SortedSet, Map, Lis…

作者头像 李华
网站建设 2026/4/16 2:33:54

100 万行文本挑战(1 Million Lines File Processing Challenge)

100 万行文本挑战指的是:在单机环境下,不使用分布式框架,对百万行级别文本数据进行高效、稳定、可解释的读取与统计处理。关键词必须同时满足: ✅ 单机✅ 大文本(百万行是入门量级)❌ 禁止分布式&#xff0…

作者头像 李华
网站建设 2026/4/16 7:30:04

100万行文本数据(Python生成数据)

1. 生成数据代码 #!/usr/bin/env python3 # -*- coding: utf-8 -*-""" Generate large comma-separated TXT data for single-node text processing. Each line one record, fields separated by , (no quotes). """import argparse import da…

作者头像 李华
网站建设 2026/4/16 7:22:10

【一遍搞定】Windows终端Windows Terminal一键配置Git Bash

​ 打开Windows Terminal,点击标签栏右侧下三角,如果没有Git Bash选项则需要进行配置 需要找到bash.exe和ico图标路径 右键复制路径,以本人设备为例,路径为D:\Git\bin\bash.exe, D:\Git\mingw64\share\git\git-for-windows.ico…

作者头像 李华
网站建设 2026/4/16 7:21:01

论文查重标准解读:9大平台+工具对比排名+

论文查重标准解读:9大平台工具对比排名论文查重标准解读:9大平台工具对比排名创作指南核心AI论文工具对比速览工具名称核心优势适用场景生成速度特色功能Aibiye多模型融合长文本理解全学科论文初稿20-30分钟文献查找自动图表生成Aicheck专业适配低重复率…

作者头像 李华
网站建设 2026/4/16 7:29:01

论文AI生成网站排名:9大平台+开源开发工具

论文AI生成网站排名:9大平台开源开发工具 论文生成源码排名:9大平台开源开发工具 核心工具对比速览 工具名称 核心功能 处理速度 适用场景 独特优势 aibiye AI论文生成降重 15-20分钟 论文初稿创作 多学科适配语义保留 aicheck AIGC检测降重…

作者头像 李华