当前位置: 首页 > news >正文

SpringBoot学习日记(二)

Bean的生命周期

这个相信大家或多或少都有了解,网上也有很多类似的帖子,但今天我想用不同的角度去解读一下。

首先就是这个图,这个就是我们Spring项目启动后,会加载Bean到Spring容器的一个过程,大家可以了解一下,但是主包想把这个流程说清楚点、简单点,有时间的小伙伴可以根据这个流程去查看一下源码。

首先就是从我们的项目启动开始说起,我们说了Spring会加载这个上下文,这个上下文又很多东西,里面有我们需要的Bean信息也就是BeanDefinition,他记录了我们每一个Bean的信息。他怎么来的?

默认情况下会被加载的Bean

  1. 配置类中定义的Bean

    • 使用@Configuration注解的类中通过@Bean定义的所有Bean
    • 除非明确指定了懒加载(@Lazy)
  2. 组件扫描发现的Bean

    • @Component及其派生注解标记的类(@Service@Repository@Controller等)
    • @ComponentScan指定包路径下的这些类
  3. Spring Boot自动配置的Bean

    • META-INF/spring/auto-configuration中定义的自动配置类
    • 条件满足时(@Conditional系列注解)才会加载
  4. 基础设施Bean

    • Spring框架自身需要的Bean(如BeanPostProcessor实现类)
    • 各种Aware接口的实现类

会被加载到BeanDefinition的只会是Bean而不是普通的Java类,这个要注意了,Bean和Java类上一期也说明白了。加载完后会调用刷新上下文的方法,这个方法中会创建BeanFactory,然后这个BeanFactory会get这个BeanDefinition的信息,然后会执行postProcessBeanFactory方法把BeanDefinition中的占位符(比如yml中填的数据库密码)替换或者修改特定Bean的信息为接下来创建Bean做准备,然后开始创建单例Bean实例化,通过反射调用构造函数创建Bean实例,进行了属性填充(依赖注入)、注入其他Bean依赖(@Autowired等)从JVM的角度来说,就是在堆中申请了内存创建了对象把一些基础属性填充了。然后就是初始化,注入简单属性值 Aware接口回调等操作,这个Aware是干啥的呢?

接口名称方法签名注入对象典型用途
BeanNameAwaresetBeanName(String name)Bean 在容器中的名称日志打印、动态代理标识
BeanClassLoaderAwaresetBeanClassLoader(ClassLoader cl)加载该Bean的类加载器类加载相关操作
BeanFactoryAwaresetBeanFactory(BeanFactory bf)创建该Bean的BeanFactory编程式获取其他Bean
EnvironmentAwaresetEnvironment(Environment env)环境配置对象读取环境变量和属性文件
ResourceLoaderAwaresetResourceLoader(ResourceLoader rl)资源加载器读取类路径/文件系统资源
ApplicationEventPublisherAwaresetApplicationEventPublisher(...)事件发布器发布应用事件
ApplicationContextAwaresetApplicationContext(...)应用上下文获取完整的容器功能

简单来说就是告诉当前这个Bean,他在Spring容器中叫什么名字、谁加载了他、加载的上下文是什么,就是给这个Bean发一个出生证明,为的就是提前让其他Bean或者需要使用它的类知道他已经被实例化了开始初始化了,不需要重复通过反射注册多个Bean了。

 BeanPostProcessor 

这个分为前置操作和后置操作,作用就如同下面的表格。

特性前置处理后置处理
调用时机Aware回调后,初始化方法前初始化方法执行后
主要用途注解处理、环境准备AOP代理生成、对象增强
能否替换Bean可以可以(更常见)
典型处理器InitDestroyAnnotationBeanPostProcessorAbstractAutoProxyCreator
性能影响较小较大(可能创建代理)
使用频率较高(处理基础注解)较高(AOP场景)

好了经历上面的这些步骤,一个Bean就完完整整的被创建出来并被Spring容器管理了,后面就是Bean的使用过程,和销毁过程了,这个其实也没什么好说的,现在问大家一个问题,Bean会被GC回收吗?我相信大家看过主包的JVM系列应该很容易得到答案,答案就是不可能的!为什么?因为我们的JVM是使用可达性分析算法去标记堆对象的,而Bean是被Spring容器管理的,那么就一定是可达的所以就一定不会被回收,明白了吗?Bean被销毁通常情况下都是程序结束了,或者设置了Bean的作用域,原型模式就是每次被依赖注入都会产生新的对象,那么这种肯定是会被GC回收的因为他不受Spring容器管理,使用这种Bean的类应该负起清理他的责任,也就是手动释放这个Bean的资源。也就是Bean的销毁要么就是程序结束了,要么就是手动释放了,当然这个并不绝对,这个只是大多数情况下的。

总结

本篇主要介绍了Bean的生命周期,结合JVM进行解读,没有涉及到源码,有兴趣的小伙伴可以通过启动类的run方法一层一层剖析,好了下期见。

http://www.dtcms.com/a/323259.html

相关文章:

  • Day38 Dataset和Dataloader类
  • Git 核心概念与操作全指南(含工作区、暂存区、版本库详解)
  • VisionMoE本地部署的创新设计:从架构演进到高效实现
  • python的format易混淆的细节
  • Java 实现企业级服务器资源监控系统(含 SSH 执行 + 邮件通知 + Excel 报表)
  • 欧拉公式的意义
  • 202506 电子学会青少年等级考试机器人六级器人理论真题
  • 通用AGI到来,记忆仍需要一点旧颜色
  • 【狂飙AGI】2025年上半年中文大模型综合性测评
  • [已解决]VSCode右键菜单消失恢复
  • 用户需求调研后的信息如何整理
  • 大语言模型提示工程与应用:LLMs文本生成与数据标注实践
  • 需求管理流程规范
  • 强化学习概论(1)
  • Android 锁屏图标的大小修改
  • android15哪些广播可以会走冷启动或者用于保活呢?
  • 探索Trae:使用Trae CN爬取 Gitbook 电子书
  • 【Doris】实时分析型数据库
  • 走遍美国5 The Right Magic 钓鱼秘决
  • 【Python 语法糖小火锅 · 第 3 涮】
  • 【RabbitMQ】高级特性—TTL、延迟队列详解
  • Java 中的编译与反编译:全面解析与实践指南
  • drippingblues靶机
  • 四边形(梯形、平行四边形、矩形、菱形和正方形)
  • [贪心]田忌赛马
  • Aurora接口FPGA设计
  • QT Creator 5.14.2安装
  • 卷板矫平机:给一张钢板做“拉伸放松操”
  • 北大回应录取通知书被指存在语句问题
  • Claude Code 与 Cursor 技术对比:架构差异与适用场景分析