咱们唠一下:单例Bean的“出生记”——从“零”到“成品”的全过程

我们先了解一下Bean是如何创建出来的,好的开头是成功的一半,不然看再多内容也是一知半解 ,老规矩先赞后看 你一定能学会 ~ 👍 💗 ~

想象你开了个机器人组装厂(这就是Spring容器),专门生产各种功能的机器人(Bean)。每个机器人都得按流程来,从"一张图纸"到"能干活"的成品,总共分六步。今天咱们就跟着一个叫"小A"的机器人(单例Bean),看看它咋从"裸体骨架"变成"合格成品",最后住进"成品仓库"(一级缓存)的。

第一步:先看"生产图纸"------BeanDefinition解析

工厂接单前,得先有"图纸"才知道咋造机器人。这个图纸就是BeanDefinition(你可以理解为"机器人说明书"),上面写着:

  • 类名(比如"小A"是UserService.class);
  • 作用域(默认"单例",整个工厂只造一个);
  • 依赖啥零件(比如"小A"需要"订单机器人"B当零件);
  • 初始化方法(比如造完后要"通电测试")。

这些图纸在工厂启动时就扫出来了(比如你写的@Service@Component注解),统一存到"图纸库"(beanDefinitionMap)里,等着开工。

第二步:搭"裸体骨架"------实例化(创建原始对象)

终于要造"小A"了!工人师傅(Spring容器)先按图纸找个空工位,用构造函数 (机器人的"骨架模具")搭个"裸体骨架"------这就是实例化

  • 比如new UserService(),得到一个"光溜溜"的对象,属性都是默认值(比如依赖的"订单机器人"B是null),像个没穿衣服的骨架,站都站不稳。

第三步:发"预订券"到"工厂仓库"------三级缓存介入

骨架搭好后,师傅做了件关键的事:给"小A"发张**"预订券"** (专业名叫ObjectFactory,工厂仓库里的"三级缓存"singletonFactories存的就是这玩意儿)。

  • 这张券上写着:"谁急着用'小A'的毛坯版(早期对象),拿券来就能领!要是需要'贴膜'(AOP代理,比如加日志、事务),我现场给你贴好。"
  • 为啥发券?万一后面有别的机器人(比如B)急着要"小A"当零件,就能用这张券先领个"毛坯"顶上,别耽误生产(这就是解决循环依赖的伏笔)。

第四步:装"零件"------属性填充(依赖注入)

骨架有了,该装零件了!"小A"的说明书说"我得装个'订单机器人'B才能干活",所以师傅去零件库(缓存)找B:

  • 如果B已经造好(在"成品仓库"一级缓存):直接拿过来装上。
  • 如果B还没造:师傅放下"小A",先去造B(递归创建B,流程和"小A"一样:搭骨架→发券→装零件...)。
  • 如果B也依赖"小A"(循环依赖)
    • B找"小A"时,成品库没有(小A没造完),就去"工厂仓库"(三级缓存)找"小A"的预订券。
    • 拿券兑现:师傅现场给B一个"小A"的毛坯(裸体骨架,要贴膜就贴好),这个毛坯先放"毛坯暂存处"(二级缓存earlySingletonObjects),同时从工厂仓库拿走券。
    • B装上"小A"毛坯,继续装其他零件,等"小A"后面造好再换成品。

第五步:测试调试------初始化(完善对象)

零件装完了,"小A"还是个"半成品",得测试调试才能干活:

  1. "自我介绍" :如果"小A"实现了BeanNameAware接口,告诉它"你叫小A,住在工厂3号工位"(注入Bean名称)。
  2. "通电预热" :执行@PostConstruct注解的方法(比如"小A"启动时加载配置)。
  3. "跑冒滴漏检查" :如果实现了InitializingBean接口,调用afterPropertiesSet()(比如检查零件装紧没)。
  4. "贴膜升级" :最后看看要不要"贴膜"(AOP代理)------比如"小A"有@Transactional注解(事务),就给它套个"代理壳",让它能自动管事务。

第六步:住进"成品仓库"------放入一级缓存

测试调试全过了,"小A"现在是"完全体"机器人!师傅把它送进**"成品仓库"** (一级缓存singletonObjects),同时做两件事:

  • 把"毛坯暂存处"(二级缓存)里的"小A"毛坯扔掉(没用了);
  • 把"工厂仓库"(三级缓存)里"小A"的预订券撕了(券的使命完成)。

以后谁要"小A",直接从成品仓库拿,保证每次拿到的都是同一个(单例嘛),不用再造新的。

总结:"小A"的一生(单例Bean生成流程)

复制代码
图纸(BeanDefinition)→ 搭骨架(实例化)→ 发预订券到工厂仓库(三级缓存)→ 装零件(属性填充,循环依赖时换毛坯)→ 测试调试(初始化+AOP)→ 住进成品仓库(一级缓存)  

关键提醒

  • 三级缓存像个"临时中转站":平时可能就放张"预订券"(ObjectFactory),真有循环依赖时才换成"毛坯"(早期对象),用完就扔。
  • 没循环依赖时:预订券发了也不用,直接造完送成品库,中转站干干净净。
  • 单例Bean一辈子就住一次成品库:从生到死都在那,保证你每次用都是同一个。

这下明白了吧?Spring造Bean就像开工厂,一环扣一环,三级缓存就是那个"应急小仓库",让循环依赖的机器人也能顺利"借零件"完成组装~

相关推荐
2301_8017609314 天前
Bean 的生命周期的各个阶段
bean·springbean
东南门吹雪19 天前
Spring的Bean相关
java·spring·bean·aop
没有bug.的程序员1 个月前
Spring Boot 整合第三方组件:Redis、MyBatis、Kafka 实战
java·spring boot·redis·后端·spring·bean·mybatis
gordon~92 个月前
Spring 的bean是安全的吗
java·安全·spring·bean
bing_1585 个月前
我写的 @Service 类就是一个 Bean 吗?
spring·bean·ioc
bing_1585 个月前
在Spring Boot 开发中 Bean 的声明和依赖注入最佳的组合方式是什么?
java·spring boot·后端·bean
FAQEW8 个月前
Spring boot 中的IOC容器对Bean的管理
java·spring boot·后端·bean·ioc容器
不修×蝙蝠9 个月前
SpringBoot 第一课(Ⅲ) 配置类注解
java·spring boot·spring·bean·propertysource·profile·importresource
喝养乐多长不高9 个月前
Spring原理
java·后端·spring·bean·bean的作用域·spring自动配置·自动配置源码