bean生命周期
其实可以分成三个阶段来记:创建 → 初始化 → 销毁,初始化阶段是重点。
创建:反射调构造方法实例化,然后注入属性和依赖。
初始化:按顺序经历四步------
- Aware 回调(让 Bean 感知到容器,比如拿到
ApplicationContext) BeanPostProcessor前置处理- 执行初始化方法(
@PostConstruct→afterPropertiesSet()→init-method,三选其一或叠加) BeanPostProcessor后置处理 (AOP 代理在这里生成,返回代理对象替换原始 Bean)
销毁 :容器关闭时,执行销毁方法(@PreDestroy → destroy() → destroy-method)。
springboot启动
Spring Boot 启动的入口是 SpringApplication.run(),里面核心干了这几件事:
第一步,创建 SpringApplication 对象 :判断应用类型(是不是 Web 应用),加载 spring.factories 里的初始化器和监听器。
第二步,准备环境 :加载 application.yml / application.properties,处理命令行参数、环境变量,确定激活的 profile。
第三步,创建 Spring 容器 (ApplicationContext):根据应用类型创建对应的容器,Web 应用创建 AnnotationConfigServletWebServerApplicationContext。
第四步,刷新容器 (refresh()):这是最核心的一步------
- 执行包扫描,注册你写的 Bean
- 执行自动配置,把符合条件的自动配置类里的 Bean 也注册进来
- 实例化所有单例 Bean,走完生命周期
- 启动内嵌 Tomcat
第五步,启动完成 :发布 ApplicationReadyEvent,ApplicationRunner / CommandLineRunner 执行,服务就绪。
Spring 容器工作过程
扫描 @Component 等注解
↓
注册 BeanDefinition(只登记类信息,不创建对象)
↓
实例化 Bean(反射调构造方法 new 出来)
↓
依赖注入(解析 @Autowired,从容器找对应 Bean,反射赋值)
↓
Aware 回调(让 Bean 感知容器,拿到 ApplicationContext 等)
↓
BeanPostProcessor 前置处理
↓
执行初始化方法(@PostConstruct → afterPropertiesSet → init-method)
↓
BeanPostProcessor 后置处理(AOP 代理在这里生成)
↓
放入容器,对外提供服务
第四步 refresh()
↓
实例化所有单例 Bean
↓
这里就是 Bean 的完整生命周期:
实例化(反射调构造方法)
↓
属性注入(@Autowired)
↓
Aware 回调(获取 Bean 名称、BeanFactory、环境信息等)
↓
BeanPostProcessor 前置处理(修改属性、检查配置)
↓
初始化方法(@PostConstruct)
↓
BeanPostProcessor 后置处理(生成代理)
↓
放入容器使用
↓
容器关闭时销毁(@PreDestroy)
自动配置
@EnableAutoConfiguration 会读取 META-INF/spring.factories 中的自动配置类。底层通过 ImportSelector 动态导入这些配置类,ImportSelector 会根据条件决定哪些配置类需要生效。
每个自动配置类通常配合条件注解,如 @ConditionalOnClass、@ConditionalOnMissingBean 或 @ConditionalOnProperty,只有满足条件的 Bean 才会注册到容器。
用户如果自己定义了同类型 Bean,会覆盖默认 Bean,从而实现可定制化。
注: 读取META-INF/spring.factories(Spring Boot 2.x)或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@SpringBootApplication:是三个注解的组合:
@SpringBootConfiguration:标识这是配置类@EnableAutoConfiguration:开启自动配置,读取 spring.factories 里的自动配置类按条件装载@ComponentScan:扫描当前包及子包下所有@Component、@Service、@Repository、@Controller注解的类注册成 Bean
Spring 三级缓存解决循环依赖
先说为什么需要三级缓存,而不是直接说三个缓存是什么。
A 依赖 B,B 依赖 A,如果没有缓存机制,创建 A 时发现需要 B,去创建 B 时又发现需要 A,死锁了。解决思路是:A 实例化之后还没初始化完,先把自己暴露出去,让 B 能拿到 A 的引用,B 完成初始化后 A 再继续完成自己的初始化。
三个缓存分别存什么:
- 一级缓存:完整的 Bean,初始化完成可以直接用
- 二级缓存:半成品 Bean,实例化了但还没初始化完
- 三级缓存:Bean 的
ObjectFactory,用来按需生成早期引用,如果需要 AOP 代理在这里生成
完整过程:
创建 A,实例化后把 A 的 ObjectFactory 放入三级缓存
↓
A 注入属性,发现需要 B,去创建 B
↓
创建 B,实例化后把 B 的 ObjectFactory 放入三级缓存
↓
B 注入属性,发现需要 A,去三级缓存找到 A 的工厂
调用工厂拿到 A 的早期引用(需要代理就生成代理),放入二级缓存,删除三级缓存里的 A
↓
B 拿到 A 的早期引用,完成初始化,放入一级缓存
↓
回到 A,拿到完整的 B,A 完成初始化,放入一级缓存,删除二级缓存里的 A
为什么必须三级,二级不够:
实例化 → 属性注入 → 初始化 → BeanPostProcessor后置处理生成代理 → 放入容器
二级放 ObjectFactory:多个 Bean 依赖 A 时,每次调用工厂生成一个新代理,B 和 C 拿到的不是同一个对象,不一致。
A 实例化 → A 的 ObjectFactory 放入二级缓存
↓
A 注入属性,发现需要 B
↓
创建 B,B 注入属性发现需要 A
↓
B 调用二级缓存的 ObjectFactory 生成代理A1,注入给 B
↓
创建 C,C 注入属性发现需要 A
↓
C 调用二级缓存的 ObjectFactory 生成代理A2,注入给 C
↓
B 里持有代理A1,C 里持有代理A2,A1 和 A2 不是同一个对象 ← 问题
二级放原始对象:B 拿到原始 A,最终容器里放的是代理 A,B 持有的引用和容器里的不是同一个对象,不一致。
A 实例化 → 原始A放入二级缓存
↓
A 注入属性,发现需要 B
↓
创建 B,B 注入属性发现需要 A
↓
B 从二级缓存拿到原始A,注入进去,B 完成初始化
↓
回到 A,继续完成初始化
↓
BeanPostProcessor 后置处理 → 生成代理A
↓
代理A放入一级缓存
构造器注入无法解决:三级缓存的前提是先实例化再注入,构造器注入是实例化时就要注入,A 还没 new 出来就需要 B,放不进三级缓存,直接报错。