Spring IoC与AOP核心原理揭秘
2026/7/12 4:19:01 网站建设 项目流程

📅 Java技术面试高频题整理 - Day 1

今日知识点:Spring IoC与AOP核心机制

Spring IoC(控制反转)与AOP(面向切面编程)是Spring全家桶的核心基石,也是Java后端面试中必考的高频深挖考点。多数开发者仅会使用框架进行CRUD操作,但对底层原理认知浅薄,难以应对中高级面试的源码提问。


一、IoC控制反转核心原理

1.1 核心概念

IoC即控制反转,是Spring的核心设计思想。它将对象创建、依赖管理的控制权从开发者反转给Spring容器,实现组件解耦、统一管理和灵活复用。

传统开发方式IoC容器方式
开发者主动new对象容器自动创建、装配、管理对象
高耦合、难维护低耦合、易扩展
依赖关系硬编码依赖关系外部配置

1.2 依赖注入三种方式

① 构造器注入(Spring官方推荐)

// 保证对象初始化完成、依赖不可变、避免空指针 public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } }

② Set方法注入
适合可选依赖、动态修改依赖场景。

③ 字段注入(不推荐生产使用)
写法简洁但耦合度高,不利于单元测试。

1.3 Bean完整生命周期

实例化 → 依赖注入 → 初始化前置处理 → 初始化方法 → 初始化后置处理 → 存入单例池 → 销毁

全程由Spring容器全权管理,是面试高频源码考点。


二、Spring三级缓存解决循环依赖

2.1 循环依赖问题

循环依赖是多Bean互相依赖导致的初始化死循环。Spring通过三级缓存机制完美解决单例Setter/字段注入循环依赖问题。

2.2 三级缓存结构

缓存级别存放内容作用
一级缓存完整初始化完成的单例Bean正常获取Bean
二级缓存已实例化、未完全初始化的Bean实例提前暴露引用
三级缓存Bean工厂对象解决循环引用

2.3 核心原理

提前暴露未完成初始化的Bean引用,打破循环依赖闭环,保证Bean正常创建。

⚠️注意:仅支持单例、非构造器注入循环依赖。构造器注入循环依赖无法解决,会直接报错。


三、AOP面向切面编程

3.1 核心概念

AOP是面向切面编程,在不修改原有代码的前提下对方法进行增强,实现代码解耦、统一增强、复用通用逻辑。

典型应用场景:事务控制、日志记录、权限校验、性能监控。

3.2 两种动态代理对比

对比维度JDK动态代理CGLIB动态代理
实现原理基于接口实现基于子类继承实现
使用限制目标类必须实现接口可代理任意普通类
性能差异高版本JDK性能持平低版本JDK更优
Spring默认SpringBoot 2.0+默认CGLIB无接口类自动选用
局限性无接口无法代理无法代理final/private/static方法

3.3 五种通知类型

  • 前置通知:方法执行前
  • 后置通知:方法执行后
  • 异常通知:方法抛出异常时
  • 环绕通知:功能最全,可控制方法执行全程
  • 返回通知:方法正常返回后

四、Spring事务核心机制

4.1 事务传播机制

传播机制说明适用场景
REQUIRED(默认)支持当前事务,不存在则新建大多数业务场景
SUPPORTS支持当前事务,不存在则以非事务执行查询操作
REQUIRES_NEW新建事务,挂起当前事务独立日志记录
NESTED嵌套事务复杂业务嵌套

4.2 事务隔离级别

读未提交 → 读已提交 → 可重复读 → 串行化,逐级解决脏读、不可重复读、幻读问题。MySQL默认可重复读

4.3 事务失效七大场景(高频坑点)

  1. 方法非public修饰
  2. 同类内部方法调用,绕过AOP代理
  3. 异常被try-catch捕获,未抛出异常
  4. 事务传播机制配置错误
  5. 多线程环境下事务互不感知
  6. 数据库引擎不支持事务(如MyISAM)
  7. 只读事务、超时触发事务回滚机制失效

五、高频面试真题及标准答案

Q1:IoC的核心作用是什么?

:IoC将对象创建、依赖管理的控制权从开发者交给Spring容器。核心作用:彻底解耦组件依赖,统一管理Bean生命周期,简化代码开发,提升程序扩展性、维护性与灵活性,是Spring框架的核心根基。

Q2:Spring如何解决循环依赖?

:Spring通过三级缓存提前暴露Bean引用解决单例Setter循环依赖。流程:Bean实例化后存入三级缓存,提前暴露引用,被依赖Bean直接获取引用完成初始化,后续逐级升级缓存,打破循环依赖闭环。仅支持单例、非构造器注入循环依赖,构造器循环依赖无法解决。

Q3:JDK动态代理和CGLIB动态代理的区别?

  1. 实现原理:JDK基于接口,CGLIB基于继承子类重写方法
  2. 使用限制:JDK要求目标类实现接口,CGLIB可代理任意普通类
  3. 性能差异:低版本JDK中CGLIB更优,高版本二者持平
  4. Spring默认:SpringBoot 2.0+默认使用CGLIB
  5. 局限性:CGLIB无法代理final、private、static方法

Q4:Spring事务失效的常见场景有哪些?

  1. 方法非public修饰
  2. 同类内部方法调用,绕过AOP代理
  3. 异常被try-catch捕获
  4. 事务传播机制配置错误
  5. 多线程环境下事务互不感知
  6. 数据库引擎不支持事务
  7. 只读事务、超时触发回滚失效

六、学习建议与避坑指南

✅ 重点掌握

  • 三级缓存解决循环依赖原理
  • 两种动态代理区别及适用场景
  • 事务传播机制适配场景
  • 高频事务失效坑点

❌ 常见误区

  • 认为字段注入是最佳实践(实际不推荐)
  • 忽视构造器注入循环依赖无法解决
  • 事务注解加在private方法上
  • 同类方法调用时忽略AOP代理绕过问题

📚 延伸学习

建议结合Spring源码深入理解Bean生命周期、三级缓存实现细节、AOP代理创建过程,彻底掌握Spring框架底层运行逻辑。


明日预告:Java集合框架核心考点(HashMap源码、ConcurrentHashMap并发机制、ArrayList与LinkedList对比)


参考来源

  • 适合中高级前端vue面试的100道题目及解析_vue.js_脚本之家
  • Java面试通关⑧:Spring核心IoC/AOP全集-CSDN博客
  • Java中的final/finally/finalize与对象4种引用全解析_java_脚本之家
  • 第7篇:工厂模式面试高频题与避坑指南-CSDN博客
  • Java面试宝典:从基础到架构9-CSDN博客
  • 【Java实习面试算法冲刺】哈希!-CSDN博客

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询