一文彻底搞懂 Spring IoC(概念、原理、实现机制、DI注入、面试重点)
在学习 Spring 时,最核心的两个概念就是:
IoC
AOP
几乎所有 Spring 功能都建立在这两个基础之上。
如果说:
AOP = 功能增强
那么:
IoC = Spring 的核心基础
很多初学者会疑惑:
- 什么是 IoC?
- IoC 和 DI 是什么关系?
- Spring 是如何实现 IoC 的?
- Spring 容器到底在做什么?
@Autowired是怎么完成注入的?
本篇文章将 系统讲清 Spring IoC 的核心知识体系。
一、什么是 IoC
1 IoC 概念
IoC 全称:
Inversion of Control
控制反转
简单理解:
对象的创建与管理权
从程序员手中
交给 Spring 容器
传统代码:
java
UserService userService = new UserService();
对象由开发者创建。
而在 Spring 中:
java
@Autowired
UserService userService;
对象由:
Spring 容器创建
这就是:
控制反转
二、为什么需要 IoC
在传统 Java 开发中:
对象之间会产生大量依赖关系。
例如:
Controller
↓
Service
↓
DAO
↓
Database
如果不使用 IoC:
java
public class OrderService {
private PaymentService paymentService = new PaymentService();
}
问题:
耦合度高
难以测试
难以维护
如果依赖发生变化:
PaymentService → NewPaymentService
就必须修改代码。
而 IoC 通过容器管理对象,实现:
解耦
三、什么是 DI(依赖注入)
很多人会混淆:
IoC
DI
其实关系是:
IoC 是思想
DI 是实现方式
DI 全称:
Dependency Injection
依赖注入
例如:
java
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
}
Spring 会自动把:
PaymentService
注入到:
OrderService
中。
四、Spring IoC 容器
IoC 的实现依赖:
Spring 容器
Spring 容器负责:
创建对象
管理对象
注入依赖
维护生命周期
Spring 中主要有两个容器:
| 容器 | 说明 |
|---|---|
| BeanFactory | 基础容器 |
| ApplicationContext | 高级容器 |
一般我们使用的是:
ApplicationContext
例如:
java
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
五、Spring IoC 工作流程
Spring 启动时会经历:
1 扫描 Bean
2 注册 BeanDefinition
3 创建 Bean
4 依赖注入
5 Bean 初始化
6 Bean 放入容器
最终:
容器中存储所有 Bean
获取 Bean:
java
UserService userService = context.getBean(UserService.class);
六、Spring IoC 的实现原理
很多人会问:
@Autowired 是怎么实现注入的?
核心技术其实是:
反射
Spring 会在运行时通过反射操作对象字段。
例如一个简化模拟:
java
// 简化模拟,实际Spring实现更复杂
Class<?> clazz = OrderService.class;
// 1. 创建实例
OrderService orderService = (OrderService) clazz.newInstance();
// 2. 查找需要注入的字段
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
// 3. 获取依赖Bean(假设容器已创建)
PaymentService paymentService = container.getBean(PaymentService.class);
// 4. 设置字段可访问(因为paymentService是private的)
field.setAccessible(true);
// 5. 执行注入!这是DI的核心动作
field.set(orderService, paymentService);
}
}
这个过程就是:
依赖注入(DI)
真实 Spring 的实现要复杂得多,但核心思想就是:
反射 + 容器管理
七、Bean 的创建方式
Spring 创建 Bean 有多种方式。
1 注解方式(最常用)
java
@Component
@Service
@Repository
@Controller
例如:
java
@Service
public class UserService {
}
Spring 会自动扫描并注册 Bean。
2 @Bean 配置方式
java
@Configuration
public class AppConfig {
@Bean
public UserService userService(){
return new UserService();
}
}
3 XML 配置(旧方式)
xml
<bean id="userService" class="com.demo.UserService"/>
现在基本不再使用。
八、Spring 注入方式
Spring 支持多种注入方式。
1 属性注入(最常用)
java
@Autowired
private UserService userService;
2 构造器注入
java
public OrderService(UserService userService){
this.userService = userService;
}
优点:
更安全
推荐使用
3 Setter 注入
java
@Autowired
public void setUserService(UserService userService){
this.userService = userService;
}
九、IoC 带来的好处
使用 IoC 后:
1 降低耦合
对象之间不直接创建依赖。
2 易于测试
可以轻松替换实现类。
例如:
MockService
3 统一管理对象
对象生命周期由 Spring 管理。
4 支持 AOP
AOP 必须依赖 IoC。
十、Spring IoC 常见问题
1 为什么 @Autowired 有时失效?
原因:
对象不是 Spring 管理
例如:
java
UserService service = new UserService();
Spring 无法注入。
2 为什么 static 字段无法注入?
例如:
java
@Autowired
static UserService userService;
原因:
Spring 只管理实例对象
3 Bean 找不到怎么办?
可能原因:
没有被扫描
包路径错误
存在多个实现
十一、IoC 与 AOP 的关系
很多人会问:
IoC 和 AOP 有什么关系?
关系是:
IoC 是基础
AOP 是扩展
AOP 必须依赖:
Spring 容器
因为:
代理对象需要由容器创建
十二、IoC 面试高频问题
1 什么是 IoC?
答:
IoC 是一种设计思想,
将对象创建和管理交给容器完成。
2 IoC 和 DI 的区别?
IoC 是思想
DI 是实现方式
3 Spring IoC 容器有哪些?
BeanFactory
ApplicationContext
4 Spring 如何实现依赖注入?
核心技术:
反射
5 Bean 是什么时候创建的?
默认:
容器启动时创建
十三、Spring IoC 总结
Spring IoC 的核心思想:
对象的创建与管理
交给 Spring 容器
核心机制:
容器 + 反射 + 依赖注入
核心流程:
扫描Bean
注册BeanDefinition
创建Bean
依赖注入
初始化
放入容器
理解 IoC 之后,就能理解:
Spring 为什么能自动装配
Spring 为什么能管理 Bean
Spring 为什么能实现 AOP
因为这一切都建立在:
IoC 容器
之上。