969 字
5 分钟
Spring 核心:IoC、依赖注入与 Bean 作用域

Spring Framework 提供容器、AOP、事务等基础能力;Spring MVC 是它的 Web 模块;Spring Boot 基于这些能力,通过自动配置、依赖管理和启动约定减少项目搭建工作。本系列把三者放在一条主线上。

IoC 与 DI#

IoC 是控制反转:对象的创建、管理和依赖组装交给容器,而不由业务类自行创建完整依赖链。DI 是依赖注入,是实现这种管理方式的重要手段。

@Service
public class OrderService {
private final OrderRepository repository;
public OrderService(OrderRepository repository) {
this.repository = repository;
}
}

单构造器场景通常无需额外写 @Autowired。必需依赖优先构造器注入,便于明确约束、测试和保持字段不可重新赋值;Setter 注入可用于可选依赖等场景。

Bean 怎样注册和选择?#

@Component 标记组件,@Service、@Repository、@Controller 是更明确的角色标记;组件扫描发现这些类。@Configuration 中的 @Bean 方法适合创建第三方类型或需要显式配置的对象。

@Autowired 通常先按类型解析依赖,多个候选时可使用 @Qualifier 指定,或用 @Primary 提供优先候选。@Resource 通常优先按名称解析,在适用条件下回退到类型;不要把两者背成所有场景都只有一个固定步骤。

Bean 的生命周期#

主线是实例化、依赖注入、初始化、使用、销毁。初始化包含相关回调和 BeanPostProcessor 处理,代理通常也通过后置处理器创建。完整顺序、销毁范围与提前引用机制见 Bean 生命周期与循环依赖。

BeanFactoryPostProcessor 主要处理定义等容器元数据,BeanPostProcessor 处理创建中的实例。整个应用启动如何组织这些步骤,可补读 容器启动过程,不用第一轮逐行背 refresh 源码。

单例 Bean 是否线程安全?#

默认 singleton 表示同一容器内同一个 Bean 定义通常只创建一个实例,不是整个 JVM 所有容器只能有一个对象。prototype 表示每次向容器获取时创建新实例;Web 环境还支持 request、session 等作用域。

单例不是线程安全承诺。无状态服务通常容易安全共享;如果在服务字段中保存当前用户、可变计数或请求对象,多个线程就可能互相覆盖。线程安全取决于状态及访问协议,不能用“Spring 管理的对象”代替同步设计。

把 prototype Bean 一次性注入 singleton,也不会让每次业务调用都自动得到新实例;需要按次获取时要使用相应的 Provider 等机制。

循环依赖能否解决?#

常见问题是 A 依赖 B,B 又依赖 A。在允许配置下,部分单例的字段或 Setter 循环依赖可以通过提前引用处理;纯构造器循环、prototype 循环不能直接套用。Spring Boot 2.6 起默认禁止循环依赖。完整 A/B 流程与三级缓存职责放在 专门的生命周期文章 中;业务仍优先通过调整职责消除循环。

面试回答模板#

Spring 通过 IoC 容器创建并组装对象,DI 把依赖交给业务类。Bean 可以通过组件扫描或 @Bean 注册,生命周期包括实例化、注入、初始化与销毁。默认单例只说明容器中的实例数量,不保证线程安全。循环依赖只在部分单例注入场景和允许配置下可处理,构造器循环应优先调整设计。

自测#

  1. 单例服务字段能直接保存每个请求的用户吗?不能,容易串数据。
  2. BeanPostProcessor 与 BeanFactoryPostProcessor 作用对象相同吗?不同。
  3. 打开允许循环依赖能解决两个 Bean 的构造器互相依赖吗?不能直接解决。
Spring 核心:IoC、依赖注入与 Bean 作用域
https://blog.xqcherry.top/posts/interview/spring/spring-core-and-beans/
作者
xqcherry
发布于
2026-10-12
许可协议
CC BY-NC-SA 4.0