Spring Boot 中 IOC 详解
1. IOC 概念
IOC(Inversion of Control)即控制反转,是一种设计原则,它将对象的创建和依赖关系的管理从应用程序代码中转移到外部容器中。在传统编程中,对象之间的依赖关系是由对象自身负责创建和管理的,这会导致代码的耦合度较高。而在 IOC 模式下,对象只需要声明它所依赖的对象,由容器来负责创建和注入这些依赖对象,从而降低了组件之间的耦合度。
2. Spring Boot 中的 IOC 容器
Spring Boot 基于 Spring 框架,使用 Spring 的 IOC 容器来管理 Bean。Spring 的 IOC 容器有两种主要实现:BeanFactory
和 ApplicationContext
。ApplicationContext
是 BeanFactory
的子接口,它提供了更多的功能,如国际化支持、事件发布等,Spring Boot 默认使用 ApplicationContext
作为 IOC 容器。
3. Bean 的定义和注册
在 Spring Boot 中,可以通过多种方式定义和注册 Bean:
- 使用注解:例如
@Component
、@Service
、@Repository
、@Controller
等注解,这些注解本质上都是@Component
的派生注解,用于将一个类标记为 Spring 容器中的 Bean。import org.springframework.stereotype.Service;
@Service
public class UserService {
public String getUserName() {
return "John Doe";
}
}
- **使用 Java 配置类**:通过 @Configuration
和 @Bean
注解来定义 Bean。
```java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService();
}
}
4. IOC 容器的工作流程
- 启动阶段:当 Spring Boot 应用启动时,会创建
ApplicationContext
实例。容器会扫描指定的包路径,查找带有@Component
及其派生注解的类,以及@Configuration
注解的配置类。 - Bean 定义阶段:容器会解析这些类和配置类,将它们转换为 Bean 定义(
BeanDefinition
),并存储在容器内部的注册表中。 - Bean 创建阶段:根据 Bean 定义,容器会创建 Bean 实例。对于单例 Bean,容器会在启动时就创建实例;对于原型 Bean,会在每次请求时创建新的实例。
- 依赖注入阶段:容器会根据 Bean 之间的依赖关系,将依赖的 Bean 注入到需要的 Bean 中。
@Autowired
注解与 IOC 的结合
1. @Autowired
注解的作用
@Autowired
是 Spring 框架提供的一个注解,用于自动装配依赖的 Bean。它可以应用在构造函数、字段、方法等位置,Spring 容器会根据类型自动查找匹配的 Bean 并注入到目标对象中。
2. 在字段上使用 @Autowired
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserController {
@Autowired
private UserService userService;
public String getUserName() {
return userService.getUserName();
}
}
在上述代码中,UserController
类依赖于 UserService
类,通过在 userService
字段上使用 @Autowired
注解,Spring 容器会自动查找类型为 UserService
的 Bean 并注入到 UserController
中。
3. 在构造函数上使用 @Autowired
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
public String getUserName() {
return userService.getUserName();
}
}
从 Spring 4.3 版本开始,如果一个类只有一个构造函数,@Autowired
注解可以省略。使用构造函数注入的好处是可以保证依赖的 Bean 在对象创建时就已经被注入,避免了空指针异常。
4. 处理多个匹配的 Bean
当存在多个类型匹配的 Bean 时,@Autowired
会根据 Bean 的名称进行匹配。可以使用 @Qualifier
注解来指定具体要注入的 Bean 的名称。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class UserController {
@Autowired
@Qualifier("userServiceV2")
private UserService userService;
public String getUserName() {
return userService.getUserName();
}
}
总结
Spring Boot 的 IOC 容器负责管理 Bean 的创建和依赖关系,而 @Autowired
注解是实现依赖注入的一种便捷方式,它与 IOC 容器紧密结合,使得开发者可以更加方便地使用 Spring Boot 的依赖注入功能,降低代码的耦合度。