Spring Framework 提供容器、AOP、事务等基础能力;Spring MVC 是它的 Web 模块;Spring Boot 基于这些能力,通过自动配置、依赖管理和启动约定减少项目搭建工作。本系列把三者放在一条主线上。
IoC 与 DI
IoC 是控制反转:对象的创建、管理和依赖组装交给容器,而不由业务类自行创建完整依赖链。DI 是依赖注入,是实现这种管理方式的重要手段。
@Servicepublic 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 注册,生命周期包括实例化、注入、初始化与销毁。默认单例只说明容器中的实例数量,不保证线程安全。循环依赖只在部分单例注入场景和允许配置下可处理,构造器循环应优先调整设计。
自测
- 单例服务字段能直接保存每个请求的用户吗?不能,容易串数据。
- BeanPostProcessor 与 BeanFactoryPostProcessor 作用对象相同吗?不同。
- 打开允许循环依赖能解决两个 Bean 的构造器互相依赖吗?不能直接解决。