01-01-Spring-IOC 发表于 2026-07-09 | 更新于 2026-07-12
| 总字数: 8.2k | 阅读时长: 32分钟 | 浏览量:
Spring IOC 知识点(源码深度解析)
本文档基于 Spring Boot 3.3.9 + Java 17 + Spring Framework 6.1.17,覆盖 Spring IOC 面试高频知识点和源码核心流程。 标注 📖 的为面试高频补充知识点;标注 🔬 的为 Spring 源码深度解析。
一、IOC 核心概念 1.1 什么是 IOC(控制反转) 一句话概括 :IOC(Inversion of Control)是将对象的创建、组装、管理 的控制权从调用方转移给容器,调用方只需声明依赖,容器负责注入。
1 2 3 4 5 6 7 8 9 10 传统方式(控制权在调用方): UserService service = new UserServiceImpl(); // 调用方自己 new service.setUserDao(new UserDaoImpl()); // 调用方自己组装 IOC 方式(控制权在容器): @Service public class UserService { @Autowired private UserDao userDao; // 声明依赖,容器负责注入 }
IOC 不是一种技术,而是一种设计思想 。Spring IOC 是 IOC 思想的具体实现,通过 DI(依赖注入) 完成。IOC 和 DI 的关系是目的与手段 的关系。
1.2 什么是 DI(依赖注入) DI(Dependency Injection)是 IOC 最常见的实现方式。Spring 的 DI 有三种注入方式:
注入方式
实现
优点
缺点
构造器注入
@Autowired 在构造器上
依赖不可变、保证不为 null、便于单元测试
参数多时代码冗长
Setter 注入
@Autowired 在 setter 上
可选依赖、可重新配置
对象可能处于不完整状态
字段注入
@Autowired 在字段上
代码简洁、无冗余样板
无法不可变、难以单元测试、隐藏依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Service public class UserService { private final UserDao userDao; private final RoleDao roleDao; public UserService (UserDao userDao, RoleDao roleDao) { this .userDao = userDao; this .roleDao = roleDao; } } @Service public class UserService { @Autowired private UserDao userDao; }
1.3 IOC 容器是什么 Spring IOC 容器是一个管理 Bean 的工厂,负责读取配置 → 创建 Bean → 组装 Bean → 管理 Bean 生命周期 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ┌──────────────────────────────────────────────────────────────────┐ │ Spring IOC 容器 │ │ │ │ ┌─────────────┐ ┌──────────────────┐ │ │ │ BeanFactory │ ←── │ ApplicationContext│ ← 用户使用 │ │ │ (底层接口) │ │ (高级容器) │ │ │ └─────────────┘ └──────────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────────────────────────────────┐ │ │ │ BeanDefinition 注册表 │ │ │ │ ┌──────────┬──────────┬──────────┐ │ │ │ │ │userService│ userDao │ roleDao │ ... │ │ │ │ └──────────┴──────────┴──────────┘ │ │ │ └──────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────┐ │ │ │ 单例池 (一级缓存) │ │ │ │ ┌──────────┬──────────┬──────────┐ │ │ │ │ │userService│ userDao │ roleDao │ ... │ │ │ │ │ (实例) │ (实例) │ (实例) │ │ │ │ │ └──────────┴──────────┴──────────┘ │ │ │ └──────────────────────────────────────────┘ │ │ │ │ 输入:POJO + 配置元数据(XML / 注解 / Java Config) │ │ 输出:可运行的系统(所有依赖组装完成) │ └──────────────────────────────────────────────────────────────────┘
1.4 BeanFactory vs ApplicationContext
维度
BeanFactory
ApplicationContext
层级
底层容器接口
高级容器,继承 BeanFactory
实例化时机
延迟加载(首次 getBean 时才创建)
默认预初始化(容器启动时创建非懒加载的 singleton Bean)
功能
仅基础 DI
完整企业功能(AOP、事件、国际化、资源加载)
内存
启动快,内存占用小
启动慢,但运行期间无创建开销
使用
资源受限环境(移动端、小程序)
企业应用(绝大多数情况)
1 2 3 4 5 6 7 BeanFactory factory = new DefaultListableBeanFactory ();ApplicationContext ctx = new AnnotationConfigApplicationContext (AppConfig.class);
二、Spring IOC 容器启动流程 — 源码深度解析 🔬
本节是 IOC 源码中最核心的部分。理解 refresh() 方法的 13 个步骤,就理解了 Spring 容器的一半。
2.1 refresh() 整体流程图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 AbstractApplicationContext.refresh() — Spring 容器的"一键启动键" ┌─────────────────────────────────────────────────────────────────────┐ │ ① prepareRefresh() — 准备刷新上下文 │ │ ├── 设置启动时间、关闭标志、激活标志 │ │ ├── initPropertySources() — 初始化属性源(可由子类覆盖) │ │ └── 校验必要属性 │ ├─────────────────────────────────────────────────────────────────────┤ │ ② obtainFreshBeanFactory() — 获取或刷新 BeanFactory │ │ ├── AbstractRefreshableApplicationContext:重建工厂并加载定义 │ │ ├── GenericApplicationContext:复用构造阶段创建的 BeanFactory │ │ └── 返回 ConfigurableListableBeanFactory │ ├─────────────────────────────────────────────────────────────────────┤ │ ③ prepareBeanFactory() — 准备 BeanFactory │ │ ├── 设置 ClassLoader(类加载器) │ │ ├── 设置 SpEL 解析器 │ │ ├── 添加 ApplicationContextAwareProcessor — Aware 回调处理 │ │ └── 注册环境相关的单例(environment, systemProperties) │ ├─────────────────────────────────────────────────────────────────────┤ │ ④ postProcessBeanFactory() — BeanFactory 后置处理(空实现) │ │ └── 子类覆盖:如 Web 容器注册 request/session 作用域 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑤ invokeBeanFactoryPostProcessors() — ★ 执行 BeanFactoryPostProcessor │ │ ├── BeanDefinitionRegistryPostProcessor:修改 BeanDefinition │ │ │ └── ConfigurationClassPostProcessor — 解析 @Configuration │ │ │ @ComponentScan │ │ └── BeanFactoryPostProcessor:修改 BeanFactory 属性 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑥ registerBeanPostProcessors() — 注册 BeanPostProcessor │ │ └── 从容器中找到所有 BPP → 创建实例 → 排序 → 注册到 BeanFactory │ │ 注意:此时大多数普通业务 Bean 仍未创建 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑦ initMessageSource() — 初始化国际化资源 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑧ initApplicationEventMulticaster() — 初始化事件广播器 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑨ onRefresh() — 留给子类的扩展点 │ │ └── Spring Boot:启动内嵌 Web 服务器(Tomcat / Undertow) │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑩ registerListeners() — 注册事件监听器 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑪ finishBeanFactoryInitialization() — ★ 初始化所有单例 Bean │ │ ├── preInstantiateSingletons() — 实例化所有非延迟的 Bean │ │ │ └── getBean(beanName) — ★ Bean 创建的完整流程(见第三章) │ │ └── 触发 SmartInitializingSingleton 回调 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑫ finishRefresh() — 完成刷新 │ │ ├── 清除缓存 │ │ ├── 初始化 LifecycleProcessor │ │ └── 发布 ContextRefreshedEvent — ★ 容器启动完成事件 │ ├─────────────────────────────────────────────────────────────────────┤ │ ⑬ resetCommonCaches() — finally 中清理公共缓存(正常/异常都会调用)│ └─────────────────────────────────────────────────────────────────────┘
打断点建议 :从 AbstractApplicationContext.refresh() 开始。XML 容器可跟进 obtainFreshBeanFactory() 观察定义加载;注解容器应重点跟进 invokeBeanFactoryPostProcessors() 中的配置类解析;最后进入 finishBeanFactoryInitialization() 观察 Bean 创建。
2.2 第②步深入:BeanDefinition 加载全链路 🔬 这是“Spring 如何读取你的配置”的核心环节。不同 ApplicationContext 的 BeanDefinition 来源并不相同。以注解驱动的 AnnotationConfigApplicationContext 为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AnnotationConfigApplicationContext(AppConfig.class) │ ├── ① this() │ ├── GenericApplicationContext 构造阶段创建 DefaultListableBeanFactory │ ├── 创建 AnnotatedBeanDefinitionReader │ │ └── AnnotationConfigUtils.registerAnnotationConfigProcessors() │ │ ├── ConfigurationClassPostProcessor │ │ ├── AutowiredAnnotationBeanPostProcessor │ │ ├── CommonAnnotationBeanPostProcessor │ │ └── EventListenerMethodProcessor 等基础设施定义 │ └── 创建 ClassPathBeanDefinitionScanner │ └── 供 context.scan(...) 编程式扫描使用 │ ├── ② register(AppConfig.class) │ └── 将 AppConfig 自身注册为 BeanDefinition │ └── ③ refresh() └── invokeBeanFactoryPostProcessors() └── ConfigurationClassPostProcessor 开始解析注解配置
为什么 ConfigurationClassPostProcessor 是核心?
它虽然是 BeanFactoryPostProcessor,但它的真正魔力在于:解析所有 @Configuration 类上的 @ComponentScan、@Bean、@Import 等注解,将它们转换为 BeanDefinition 并注册到容器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry() │ └── ConfigurationClassPostProcessor.processConfigBeanDefinitions() │ ├── ConfigurationClassParser.parse() │ ├── 解析 @ComponentScan │ │ └── ComponentScanAnnotationParser.parse() │ │ └── ClassPathBeanDefinitionScanner.doScan() │ │ ├── 通过 ASM 读取 .class 元数据 │ │ └── 注册 ScannedGenericBeanDefinition │ ├── 解析 @Import / @ImportResource / @PropertySource │ └── 收集 @Bean 方法并构建 ConfigurationClass 模型 │ └── ConfigurationClassBeanDefinitionReader.loadBeanDefinitions() ├── 将 @Bean 方法注册为 ConfigurationClassBeanDefinition ├── 注册 imported 配置类 ├── 加载 @ImportResource └── 调用 ImportBeanDefinitionRegistrar
面试要点 :构造 AnnotationConfigApplicationContext 时只是创建 reader/scanner 并注册启动配置类及基础设施 BeanDefinition;@ComponentScan、@Bean、@Import 的真正解析发生在 invokeBeanFactoryPostProcessors() 阶段。
2.3 第⑤步深入:BeanFactoryPostProcessor 执行顺序 🔬 1 2 3 4 5 6 7 8 9 10 11 12 13 14 invokeBeanFactoryPostProcessors() │ ├── 1. 执行通过 API 手动传入的 BeanDefinitionRegistryPostProcessor │ ├── 2. 执行容器中的 BeanDefinitionRegistryPostProcessor │ ├── PriorityOrdered │ │ └── ConfigurationClassPostProcessor 在这里执行 ★ │ ├── Ordered │ └── 普通处理器(循环发现本阶段新增的 BDRPP) │ ├── 3. 调用上述 BDRPP 的 postProcessBeanFactory() │ └── 4. 执行其余 BeanFactoryPostProcessor └── PriorityOrdered → Ordered → 普通
面试陷阱 :@Configuration 类本身会被 ConfigurationClassPostProcessor 再次解析,这意味着如果你的 @Configuration 类也实现了 BeanFactoryPostProcessor,它的 postProcessBeanFactory() 方法不会在第一次扫描阶段自动执行,而是需要等到它自己的 Bean 实例被创建之后。这就是为什么 Spring 官方建议不要 在 @Configuration 类上同时实现 BeanFactoryPostProcessor。
2.4 第⑪步深入:preInstantiateSingletons() 🔬 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 DefaultListableBeanFactory.preInstantiateSingletons() │ └── for (String beanName : beanDefinitionNames) │ ├── 跳过抽象类、延迟加载、作用域非 singleton 的 Bean │ ├── if (isFactoryBean(beanName)) │ └── getBean(FACTORY_BEAN_PREFIX + beanName) │ // 创建 FactoryBean 本身,而非其 getObject() 返回的对象 │ └── getBean(beanName) ← ★ 普通 Bean 的完整创建流程(见第三章) │ ├── 从缓存获取(singletonObjects) ├── 缓存未命中 → createBean() │ ├── resolveBeforeInstantiation() // InstantiationAwareBeanPostProcessor │ ├── doCreateBean() │ │ ├── createBeanInstance() // ① 实例化 │ │ ├── populateBean() // ② 属性注入 ★ │ │ └── initializeBean() // ③ 初始化 ★ │ │ ├── invokeAwareMethods() │ │ ├── applyBeanPostProcessorsBeforeInitialization() │ │ │ └── @PostConstruct 在这里由相关 BPP 调用 │ │ ├── invokeInitMethods() │ │ │ └── InitializingBean + 自定义 init-method │ │ └── applyBeanPostProcessorsAfterInitialization() │ │ └── 通常在这里生成最终 AOP 代理 │ └── 放入 singletonObjects 缓存 └── 返回 Bean 实例
三、Bean 的创建流程 — 三级缓存与循环依赖 🔬
这是 Spring IOC 源码中最精彩的设计,也是面试必考点。
3.1 三级缓存定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { private final Map<String, Object> singletonObjects = new ConcurrentHashMap <>(256 ); private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap <>(16 ); private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap <>(16 ); private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap <>(16 )); }
三级缓存的作用 :
缓存
级别
存放内容
作用
singletonObjects
一级
完整的 Bean 实例
所有单例 Bean 的最终存放位置
earlySingletonObjects
二级
未完成注入的早期 Bean
循环依赖时提供中间状态的对象
singletonFactories
三级
ObjectFactory(能生成 Bean 的工厂)
允许在 Bean 创建早期暴露其引用,支持生成代理对象
3.2 为什么是三级而不是二级? 这是面试官最爱追问的问题。关键在于 AOP 代理的时机 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 如果只有两级缓存(去掉 singletonFactories): A 依赖 B,B 依赖 A(循环依赖) 1. A 创建 → 实例化 A → 放入二级缓存(此时还是原始对象)→ 注入 B 2. B 创建 → 实例化 B → 从二级缓存拿到 A(原始对象)→ 注入 A → B 完成 3. A 完成注入 B → A 初始化 → AOP 创建 A 的代理对象 问题:B 持有的 A 是原始对象,而容器中的 A 是代理对象 → 不一致!★★★ 三级缓存解决: 1. A 创建 → 实例化 A → 放入三级缓存(lambda: getEarlyBeanReference)→ 注入 B 2. B 创建 → 实例化 B → 从三级缓存获取 A → 调用 getEarlyBeanReference() → ★ 在这里判断 A 是否需要 AOP 代理 → 如果需要,创建早期代理对象返回给 B → 放入二级缓存,从三级缓存移除 3. A 完成注入 B → A 初始化 → AOP 后置处理 → 发现早期代理已存在 → 使用早期代理(不重复创建)★ 结果:B 持有的 A 和容器中的 A 是同一个代理对象 → 一致 ✅
面试话术 :”三级缓存的核心价值不是解决普通循环依赖,而是解决 AOP 代理下的循环依赖 。singletonFactories 中的 getEarlyBeanReference() 允许在 Bean 初始化早期就决定是否需要代理,确保循环依赖双方拿到的都是正确版本。”
3.3 doCreateBean() 完整流程 🔬 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 protected Object doCreateBean (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); Object bean = instanceWrapper.getWrappedInstance(); applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); boolean earlySingletonExposure = (mbd.isSingleton() && this .allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false ); if (earlySingletonReference != null ) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } } } return exposedObject; }
3.4 循环依赖场景全景图谱
以下“可解决”描述指 Spring Framework 在 allowCircularReferences = true 时的能力。Spring Boot 3.3.9 默认禁止循环依赖;除非显式设置 spring.main.allow-circular-references=true,否则普通字段/Setter 循环依赖也会启动失败。生产代码应优先通过重构消除循环依赖,而不是开启该配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 场景一:普通单例 Bean 的字段/Setter 循环依赖 → Framework 条件可解决 A ←→ B 两者都是普通对象,无需代理 场景二:AOP 代理下的字段/Setter 循环依赖 → Framework 条件可解决 A ←→ B 其中 A 被 @Transactional / @Aspect 代理 场景三:构造器循环依赖 → ❌ 无法解决 ★ class A { public A(B b) {} } class B { public B(A a) {} } 原因:构造器注入发生在实例化阶段,此时对象还没有创建出来,无法提前暴露到缓存 场景四:prototype 循环依赖 → ❌ 无法解决 原因:prototype Bean 不会被放入缓存,每次都是新创建 场景五:@Async + 循环依赖 → ❌ 可能无法解决 原因:早期暴露的对象可能与 @Async 后处理器生成的最终代理不一致 场景六:@Lazy 打破构造器循环依赖 → ✅ 可解决 class A { public A(@Lazy B b) {} } 原理:注入的不是 B 本身,而是 B 的代理,代理在首次使用时才真正获取 B
3.5 getBean() / doGetBean() 的完整调用链 🔬 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 protected <T> T doGetBean (String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) { String beanName = transformedBeanName(name); Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); return bean; } if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException (beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { return parentBeanFactory.getBean(name); } markBeanAsCreated(beanName); RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); String[] dependsOn = mbd.getDependsOn(); for (String dep : dependsOn) { getBean(dep); } if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { return createBean(beanName, mbd, args); }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { Object prototypeInstance = createBean(beanName, mbd, args); bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); Scope scope = this .scopes.get(scopeName); Object scopedInstance = scope.get(beanName, () -> { return createBean(beanName, mbd, args); }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } return bean; }
打断点建议 :doGetBean() 是跟踪单个 Bean 创建的最佳入口。可以在 getSingleton(beanName) 的缓存查询处、createBean() 调用处、以及 getObjectForBeanInstance() 处分别打断点,跟踪 Bean 从缓存到创建的全过程。
四、依赖注入的实现机制 🔬 4.1 @Autowired 的处理流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); metadata.inject(bean, beanName, pvs); return pvs; }
4.2 按类型查找依赖 — resolveDependency() 🔬 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public Object doResolveDependency (DependencyDescriptor descriptor, ...) { Object shortcut = descriptor.resolveShortcut(this ); if (shortcut != null ) return shortcut; Class<?> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null ) { return resolveEmbeddedValue((String) value); } Object multipleBeans = resolveMultipleBeans(descriptor, ...); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, ...); } return null ; } if (matchingBeans.size() > 1 ) { autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null ) { throw new NoUniqueBeanDefinitionException (type, matchingBeans.keySet()); } } return getBean(autowiredBeanName); }
4.3 @Resource 与 @Autowired 的区别 📖
维度
@Autowired
@Resource
来源
Spring 注解
Jakarta Common Annotations(jakarta.annotation)
注入方式
默认按类型(byType)
默认按名称(byName)
处理器
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
required
支持 required = false
不支持,始终注入
查找逻辑
按类型筛选,结合 @Qualifier、@Primary 等消歧
显式名称严格按名称;默认名称在允许回退时可按类型匹配
适用位置
构造器、字段、setter、方法参数
字段、setter
1 2 3 4 5 6 7 8 9 10 11 @Autowired private UserService userService; @Autowired @Qualifier("userServiceImpl") private UserService userService;@Resource(name = "userServiceImpl") private UserService userService;
实际使用建议 :Spring 项目中常优先使用 @Autowired 或构造器注入,因为它们与 Spring 生态集成更自然;如果项目希望降低对 Spring 注解的直接依赖,可以考虑 @Resource。
五、Bean 生命周期详解 5.1 完整生命周期图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ┌────────────────────────────────────────────────────────────────────────┤ │ Spring Bean 完整生命周期 │ ├────────────────────────────────────────────────────────────────────────┤ │ │ │ 1. 实例化 (Instantiation) │ │ └── createBeanInstance() │ │ ├── 通过 Supplier 回调(编程式注册的 instanceSupplier) │ │ ├── 通过 FactoryMethod(如 @Bean 方法) │ │ ├── 通过构造器实例化(候选构造器、单构造器或默认构造器) │ │ └── InstantiationAwareBeanPostProcessor 可在此返回代理替代实例化 │ │ │ │ 2. 属性注入 (Populate) │ │ └── populateBean() │ │ ├── InstantiationAwareBeanPostProcessor.postProcessProperties() │ │ │ └── AutowiredAnnotationBeanPostProcessor → @Autowired 注入│ │ │ └── CommonAnnotationBeanPostProcessor → @Resource 注入 │ │ └── 按名称自动装配(byName) │ │ │ │ 3. Aware 回调 │ │ └── invokeAwareMethods() │ │ ├── BeanNameAware.setBeanName() │ │ ├── BeanClassLoaderAware.setBeanClassLoader() │ │ └── BeanFactoryAware.setBeanFactory() │ │ │ │ 4. BeanPostProcessor 前置处理(初始化前) │ │ └── applyBeanPostProcessorsBeforeInitialization() │ │ └── ApplicationContextAwareProcessor │ │ ├── EnvironmentAware │ │ ├── EmbeddedValueResolverAware │ │ ├── ResourceLoaderAware │ │ ├── ApplicationEventPublisherAware │ │ ├── MessageSourceAware │ │ └── ApplicationContextAware ★ │ │ └── InitDestroyAnnotationBeanPostProcessor │ │ └── 调用 @PostConstruct │ │ │ │ 5. 初始化 (Initialization) │ │ └── invokeInitMethods() │ │ ├── InitializingBean.afterPropertiesSet() │ │ └── 自定义 init-method(@Bean(initMethod = "init")) │ │ │ │ 6. BeanPostProcessor 后置处理(初始化后)★ │ │ └── applyBeanPostProcessorsAfterInitialization() │ │ └── AbstractAutoProxyCreator.wrapIfNecessary() │ │ └── 通常在此生成最终 AOP 代理;循环依赖时可能提前暴露代理 │ │ │ │ ═══════════════ Bean 就绪,可被使用 ═══════════════ │ │ │ │ 7. 销毁 (Destruction) │ │ └── destroy() │ │ ├── @PreDestroy 方法 │ │ ├── DisposableBean.destroy() │ │ └── 自定义 destroy-method │ │ │ └────────────────────────────────────────────────────────────────────────┘
5.2 生命周期中的关键时序陷阱 📖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 陷阱 1:构造器中不能使用 @Autowired 注入的依赖 @Service public class UserService { @Autowired private UserDao userDao; // ❌ 此时还是 null! public UserService() { userDao.find(); // NPE!构造器先于 @Autowired 执行 } } 正确方式:使用构造器注入 @Service public class UserService { private final UserDao userDao; public UserService(UserDao userDao) { // ✅ 构造器参数由 Spring 传入 this.userDao = userDao; userDao.find(); // 安全 } } 陷阱 2:@PostConstruct 中 this.xxx() 不走 AOP @Service public class UserService { @PostConstruct public void init() { this.transactionalMethod(); // ❌ 事务不生效!代理尚未创建 } @Transactional public void transactionalMethod() { ... } } 陷阱 3:ApplicationContextAware 在 @PostConstruct 之前执行 顺序:构造器 → @Autowired → ApplicationContextAware → @PostConstruct 所以 @PostConstruct 中可以使用 ApplicationContext
六、Bean 作用域 📖 6.1 五种作用域
作用域
说明
使用场景
singleton
每个 IoC 容器中仅一个实例
默认,无状态 Bean(Service、Dao、Controller)
prototype
每次获取都创建新实例
有状态 Bean、每次任务独立的处理器
request
每个 HTTP 请求一个实例
Web 应用中的请求级数据
session
每个 HTTP Session 一个实例
用户会话数据
application
每个 ServletContext 一个实例
Web 应用全局数据
6.2 singleton vs prototype 的选择 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Service public class UserService { } @Scope("prototype") @Service public class ExportTask { private final List<Object> taskData = new ArrayList <>(); }
面试要点 :singleton Bean 中注入 prototype Bean 时,prototype 不会每次都创建新实例(因为 singleton 只在创建时注入一次)。解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Autowired private ApplicationContext ctx;public void doExport () { ExportService service = ctx.getBean(ExportService.class); } @Lookup public ExportService getExportService () { return null ; }@Autowired private ObjectProvider<ExportService> provider;public void doExport () { ExportService service = provider.getObject(); }
6.3 自定义作用域 📖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Component public class ThreadScope implements Scope { private final ThreadLocal<Map<String, Object>> threadScope = ThreadLocal.withInitial(HashMap::new ); @Override public Object get (String name, ObjectFactory<?> objectFactory) { Map<String, Object> scope = threadScope.get(); return scope.computeIfAbsent(name, k -> objectFactory.getObject()); } @Override public Object remove (String name) { return threadScope.get().remove(name); } }
七、FactoryBean 与 BeanFactory 📖 7.1 概念对比
维度
BeanFactory
FactoryBean
是什么
Spring IOC 容器的顶层接口
一种特殊的 Bean,用于创建复杂对象
职责
管理所有 Bean 的创建和依赖
自定义单个 Bean 的创建逻辑
核心方法
getBean()
getObject()
使用者
Spring 框架内部
开发者和框架(如 MyBatis、Feign)
7.2 FactoryBean 使用示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Component public class SqlSessionFactoryBean implements FactoryBean <SqlSessionFactory> { @Override public SqlSessionFactory getObject () throws Exception { return new SqlSessionFactoryBuilder ().build(configuration); } @Override public Class<?> getObjectType() { return SqlSessionFactory.class; } @Override public boolean isSingleton () { return true ; } }
面试要点 :
getBean("myFactoryBean") → 返回 getObject() 的对象
getBean("&myFactoryBean") → 返回 FactoryBean 本身(前缀 & 是 BeanFactory.FACTORY_BEAN_PREFIX)
MyBatis 的 Mapper 接口、Feign 的客户端接口都是通过 FactoryBean 创建的代理
八、@Configuration 与 @Bean 的全量模式 vs 轻量模式 🔬 8.1 全量模式(Full Mode) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Configuration public class AppConfig { @Bean public UserDao userDao () { return new UserDaoImpl (); } @Bean public UserService userService () { return new UserService (userDao()); } }
原理 :@Configuration(proxyBeanMethods = true) 会使 Spring 通过 CGLIB 生成 AppConfig 的子类代理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class AppConfig$$SpringCGLIB$$0 extends AppConfig { @Override public UserDao userDao () { if (beanFactory.containsSingleton("userDao" )) { return beanFactory.getBean(UserDao.class); } return super .userDao(); } @Override public UserService userService () { return super .userService(); } }
8.2 轻量模式(Lite Mode) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Component public class AppConfig { @Bean public UserDao userDao () { return new UserDaoImpl (); } @Bean public UserService userService () { return new UserService (userDao()); } }
推荐改为方法参数注入:
1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration(proxyBeanMethods = false) public class AppConfig { @Bean public UserDao userDao () { return new UserDaoImpl (); } @Bean public UserService userService (UserDao userDao) { return new UserService (userDao); } }
选择建议 :
proxyBeanMethods = true(默认):需要在 @Bean 方法间保持单例语义 → 更安全,但多一次 CGLIB 代理生成
proxyBeanMethods = false:@Bean 方法间无直接调用依赖 → 避免配置类 CGLIB 增强开销
九、Spring IOC 扩展点 🔬 Spring IOC 提供了丰富的扩展点,理解这些扩展点是开发框架级功能的基础。
9.1 BeanFactoryPostProcessor — 修改 BeanDefinition 1 2 3 4 5 6 7 8 9 @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) { } }
9.2 BeanPostProcessor — 修改 Bean 实例 1 2 3 4 5 6 7 8 9 10 11 12 public interface BeanPostProcessor { default Object postProcessBeforeInitialization (Object bean, String beanName) { return bean; } default Object postProcessAfterInitialization (Object bean, String beanName) { return bean; } }
9.3 InstantiationAwareBeanPostProcessor — 控制实例化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { default Object postProcessBeforeInstantiation (Class<?> beanClass, String beanName) { return null ; } default boolean postProcessAfterInstantiation (Object bean, String beanName) { return true ; } default PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) { return pvs; } }
9.4 扩展点实践示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Component public class CustomAnnotationBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization (Object bean, String beanName) { Field[] fields = bean.getClass().getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(CustomInject.class)) { field.setAccessible(true ); } } return bean; } }
9.5 扩展点执行顺序总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 容器启动: 1. BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry() 2. 同一批 BeanDefinitionRegistryPostProcessor.postProcessBeanFactory() 3. 其余 BeanFactoryPostProcessor.postProcessBeanFactory() Bean 生命周期: 4. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() ← 可返回代理 5. 实例化(构造器 / FactoryMethod) 6. MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition() ← 解析注入元数据 7. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() ← 决定是否继续属性填充 8. InstantiationAwareBeanPostProcessor.postProcessProperties() ← @Autowired 注入 9. Aware 接口回调 10. BeanPostProcessor.postProcessBeforeInitialization() ← 包含 @PostConstruct 11. InitializingBean → init-method 12. BeanPostProcessor.postProcessAfterInitialization() ← 通常生成最终 AOP 代理 容器关闭: 13. @PreDestroy → DisposableBean → destroy-method
十、生产最佳实践 10.1 注入方式的选择 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Service public class UserService { @Autowired private UserDao userDao; @Autowired private RoleService roleService; } @Service public class UserService { private final UserDao userDao; private final RoleService roleService; public UserService (UserDao userDao, RoleService roleService) { this .userDao = userDao; this .roleService = roleService; } } @Service @RequiredArgsConstructor public class UserService { private final UserDao userDao; private final RoleService roleService; }
10.2 避免 Bean 名称冲突 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Component public class MessageService { }@Component public class AliyunMessageService extends MessageService { }@Component("messageService") public class MessageServiceImpl implements IMessageService { }@Component("aliyunMessageService") public class AliyunMessageServiceImpl implements IMessageService { }@Autowired @Qualifier("messageService") private IMessageService messageService;@Component @Primary public class DefaultMessageService implements IMessageService { }@Autowired private List<IMessageService> messageServices;
10.3 构造器循环依赖的最佳解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Service public class ServiceA { private final ServiceB serviceB; public ServiceA (ServiceB serviceB) { this .serviceB = serviceB; } } @Service public class ServiceB { private final ServiceA serviceA; public ServiceB (ServiceA serviceA) { this .serviceA = serviceA; } } @Service public class ServiceA { private final ServiceB serviceB; public ServiceA (@Lazy ServiceB serviceB) { this .serviceB = serviceB; } }
10.4 Bean 的懒加载策略 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 spring: main: lazy-initialization: true # 所有 Bean 延迟初始 @ComponentScan(basePackages = "com.example", lazyInit = true) @Component @Lazy public class HeavyInitService { ... }@Autowired @Lazy private HeavyInitService heavyInitService;
10.5 优雅关闭最佳实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Service public class ResourceService implements DisposableBean { @Override public void destroy () { closeResources(); } } server: shutdown: graceful # 优雅关闭 spring: lifecycle: timeout-per-shutdown-phase: 30s # 每个阶段超时 30 秒 @PreDestroy public void shutdown () { executor.shutdown(); try { if (!executor.awaitTermination(30 , TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); Thread.currentThread().interrupt(); } }
10.6 避免在 @Configuration 中使用字段注入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Configuration public class AppConfig { @Autowired private DataSource dataSource; @Bean public JdbcTemplate jdbcTemplate () { return new JdbcTemplate (dataSource); } } @Configuration public class AppConfig { @Bean public JdbcTemplate jdbcTemplate (DataSource dataSource) { return new JdbcTemplate (dataSource); } }
10.7 启动性能优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @ComponentScan(basePackages = "com.example") @ComponentScan(basePackages = {"com.example.order", "com.example.user"}) @SpringBootApplication(exclude = { SomeUnusedAutoConfiguration.class }) @Configuration(proxyBeanMethods = false) public class AppConfig { ... }
十一、常见面试题及解答思路 11.1 Spring IOC 的原理是什么? 答题框架 :
一句话总结 :IOC 是一种设计思想,将对象创建和依赖管理的控制权从程序转移到 Spring 容器。容器通过读取配置元数据(注解/XML)生成 BeanDefinition,再根据 BeanDefinition 创建 Bean 实例并完成依赖注入。
展开核心流程 :
容器启动 → refresh() → 加载 BeanDefinition(ConfigurationClassPostProcessor)
invokeBeanFactoryPostProcessors() → 解析 @ComponentScan、@Bean 等
finishBeanFactoryInitialization() → preInstantiateSingletons() → getBean()
getBean() → createBean() → doCreateBean()
createBeanInstance() → 实例化
populateBean() → 依赖注入
initializeBean() → 初始化 + AOP 代理
关键组件 :DefaultListableBeanFactory(容器核心)、BeanDefinition(Bean 元数据)、BeanPostProcessor(扩展点)、三级缓存(循环依赖)
11.2 Spring 如何解决循环依赖? 答题框架 :
先说明前提 :Spring Framework 只有在 allowCircularReferences = true 时才会尝试解决部分循环依赖;Spring Boot 3.3.9 默认值为 false。
三级缓存是核心机制 :singletonObjects(一级)、earlySingletonObjects(二级)、singletonFactories(三级)。
流程 :A 和 B 通过字段或 Setter 形成单例循环依赖
创建 A → 实例化 A → 将 A 的 ObjectFactory 放入三级缓存 → 注入 B
创建 B → 实例化 B → 注入 A(从三级缓存拿到 A 的早期引用)→ B 完成
A 拿到 B → 继续初始化 → A 完成
为什么是三级不是两级 :AOP 代理问题。如果只有两级,B 中注入的 A 可能是原始对象,而容器中的 A 是代理对象,产生不一致。三级缓存通过 getEarlyBeanReference() 在早期决定是否暴露代理,保证引用一致。
局限性 :构造器循环依赖和 prototype 循环依赖无法通过三级缓存解决。可以用 @Lazy 在部分场景打破依赖,但生产代码应优先重构,而不是开启循环依赖配置。
11.3 BeanFactory 和 ApplicationContext 的区别?
维度
BeanFactory
ApplicationContext
实例化时机
延迟加载
启动时预初始化
功能
基础 DI
AOP、事件、国际化、资源加载
内存占用
小
大
使用场景
资源受限
99% 的企业应用
11.4 @Autowired 和 @Resource 的区别?
@Autowired:Spring 注解,默认按类型(byType),可配合 @Qualifier 按名称
@Resource:JDK 注解,默认按名称(byName),找不到再按类型
处理器不同:AutowiredAnnotationBeanPostProcessor vs CommonAnnotationBeanPostProcessor
11.5 Bean 的生命周期? 1 2 3 4 5 实例化 → 属性注入 → BeanNameAware → BeanFactoryAware → ApplicationContextAware → BeanPostProcessor.before → @PostConstruct → InitializingBean → init-method → BeanPostProcessor.after(AOP 代理) → 使用 → @PreDestroy → DisposableBean → destroy-method
11.6 @Configuration 中的 proxyBeanMethods 是什么意思?
proxyBeanMethods = true(默认):CGLIB 代理配置类,保证 @Bean 方法间的调用返回的都是容器中的单例
proxyBeanMethods = false:轻量模式,不生成代理,启动更快,但 @Bean 方法间调用会创建新实例
11.7 Spring 中使用了哪些设计模式?
设计模式
Spring 中的应用
工厂模式
BeanFactory、FactoryBean
单例模式
Bean 的默认作用域 singleton
代理模式
AOP、@Lazy、@Configuration 的 proxyBeanMethods
模板模式
JdbcTemplate、RestTemplate、AbstractApplicationContext.refresh()
观察者模式
ApplicationListener、@EventListener
责任链模式
AOP 的拦截器链、BeanPostProcessor 链
策略模式
InstantiationStrategy(实例化策略)
装饰器模式
BeanWrapper
11.8 如何排查 Bean 未注入的问题?
十二、扩展阅读与深入方向
Spring 源码阅读路线 :AbstractApplicationContext.refresh() → DefaultListableBeanFactory → AbstractAutowireCapableBeanFactory.doCreateBean() → DefaultSingletonBeanRegistry(三级缓存)
Spring Boot 自动配置原理 :@SpringBootApplication → @EnableAutoConfiguration → AutoConfigurationImportSelector → META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports → xxxAutoConfiguration
Spring 6.x / Spring Boot 3.x 新特性 :AOT 编译(GraalVM Native Image)、虚拟线程支持、ProblemDetail(RFC 7807)
Spring 与 Jakarta EE :Spring 6 全面迁移到 Jakarta EE 9+ 命名空间(javax.* → jakarta.*)
IOC 的替代品 :Google Guice(轻量级 DI)、Dagger 2(编译时 DI)、Micronaut(AOT DI)
十三、调试 Spring IOC 源码的断点建议
调试目标
断点位置
关键类
容器启动入口
refresh() 方法第一行
AbstractApplicationContext
BeanDefinition 加载
invokeBeanFactoryPostProcessors()
AbstractApplicationContext
@ComponentScan 解析
doScan()
ClassPathBeanDefinitionScanner
@Bean 方法解析
loadBeanDefinitionsForConfigurationClass()
ConfigurationClassBeanDefinitionReader
Bean 创建入口
doGetBean()
AbstractBeanFactory
三级缓存获取
getSingleton(beanName, true)
DefaultSingletonBeanRegistry
Bean 实例化
createBeanInstance()
AbstractAutowireCapableBeanFactory
依赖注入
populateBean()
AbstractAutowireCapableBeanFactory
@Autowired 处理
postProcessProperties()
AutowiredAnnotationBeanPostProcessor
AOP 代理生成
wrapIfNecessary()
AbstractAutoProxyCreator
Bean 初始化
initializeBean()
AbstractAutowireCapableBeanFactory
三级缓存 lambda
addSingletonFactory()
AbstractAutowireCapableBeanFactory
调试技巧 :
先写一个最小 Demo(两个相互依赖的 Service),启动调试,跟着 refresh() 一步步走
重点跟 finishBeanFactoryInitialization() → preInstantiateSingletons() → getBean() 这条链路
观察三级缓存在循环依赖时的变化:何时放入、何时取出、何时升级
使用 IDEA 的 Evaluate Expression 查看 singletonObjects、earlySingletonObjects、singletonFactories 的内容变化
本文档编写于 2026-06-24,基于 Spring Boot 3.3.9 + Java 17 + Spring Framework 6.1.17。 建议结合 Spring 源码调试,加深对 IOC 容器启动、Bean 创建、循环依赖解决机制的理解。 关联阅读:Spring AOP 知识点(02-01-Spring-AOP.md)、JVM 知识点(JVM.md)。