【SpringBoot从初学者到专家的成长05】SpringBoot 中控制反转 (IoC)和依赖注入(DI)的概念、技术实现与应用场景
Spring Boot 中控制反转和依赖注入
1. 控制反转 (IoC) 的概念
控制反转(Inversion of Control,IoC)是一种设计原则,主要用于解除对象之间的直接依赖关系。它通过将对象的创建和管理交给框架来实现,而不是由应用程序主动创建对象。IoC 的核心思想是控制的反转,即由容器(如 Spring 容器)负责对象的生命周期和依赖注入。
在传统的开发中,组件通常会自己创建它所依赖的其他组件(如通过 new 操作符)。而在 IoC 中,对象及其依赖关系的管理由 IoC 容器接管,开发者无需关心依赖项的创建过程。
2. 技术实现
SpringBoot 是一个全面的企业应用开发框架,它实现了 IoC 原则,并通过 依赖注入(DI,Dependency Injection) 提供了对对象依赖关系的管理。SpringBoot是 Spring Framework 的一个子项目,它进一步简化了 Spring 应用的配置和部署,使开发者更容易使用 IoC 原则来管理应用中的依赖。
2.1 依赖注入(DI)
IoC 容器通过依赖注入(Dependency Injection,DI)来实现对组件依赖关系的管理。DI 有三种主要的方式:
- 构造器注入:通过构造函数注入依赖对象。
- Setter 注入:通过 setter 方法注入依赖对象。
- 字段注入:通过字段直接注入依赖对象。
2.2 Spring 中的 Bean 管理
在 Spring 中,所有的对象(或称为组件、Bean)都由 Spring IoC 容器 来管理。容器在启动时会读取配置文件或注解,创建和管理 Bean 实例,并处理它们之间的依赖关系。
Spring 使用配置类(通过 @Configuration 注解)和 注解(如 @Component, @Service, @Repository, @Controller)来定义 Bean,并通过 @Autowired 注解将依赖注入到目标对象中。
3. 应用场景
控制反转和依赖注入在很多场景中都非常有用,特别是在以下几种情况:
- 解耦:IoC 使得各个模块之间的依赖关系松散,便于维护和扩展。各模块之间仅通过接口进行交互,而不需要知道彼此的具体实现。
- 测试驱动开发(TDD):由于 IoC 容器能够轻松地管理和替换 Bean,因此在测试中可以轻松模拟 Bean 的行为,进行单元测试。
- 配置管理:通过集中管理 Bean 配置,可以轻松修改对象的创建方式、生命周期等,无需修改业务逻辑。
- 跨应用共享:通过 IoC 容器提供的跨项目的依赖管理,可以在不同模块、应用之间共享服务,避免了重复配置。
4. Spring Boot 中的 IoC 技术实现
4.1 配置类与 Bean 定义
Spring Boot 使用注解 @Configuration 来声明一个配置类,并通过 @Bean 注解来显式定义 Bean。尽管 Spring Boot 强烈建议使用 @Component 系列注解来自动扫描 Bean,但你也可以通过 @Bean 手动定义 Bean。
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
4.2 组件扫描与自动注入
在 Spring Boot 中,你只需要在启动类上加上 @SpringBootApplication 注解,它会自动进行组件扫描,发现并注册类路径下的所有符合条件的 Bean。
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
通过 @Autowired 注解,Spring 会自动将合适的 Bean 注入到类中:
@Service
public class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
myRepository.performRepositoryAction();
}
}
4.3 构造器注入、Setter 注入与字段注入
Spring 提供了多种方式来注入依赖,其中构造器注入是推荐的方式,因为它可以确保依赖关系的强制性和不可变性。
@Service
public class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
myRepository.performRepositoryAction();
}
}
如果你想使用 Setter 注入,可以通过以下方式:
@Service
public class MyService {
private MyRepository myRepository;
@Autowired
public void setMyRepository(MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
myRepository.performRepositoryAction();
}
}
4.4 配置文件与属性注入
在 Spring Boot 中,配置信息通常存储在 application.properties 或 application.yml 文件中。你可以通过 @Value 注解注入配置文件中的属性值:
# application.properties
myapp.name=Spring Boot IoC Example
@Service
public class MyService {
@Value("${myapp.name}")
private String appName;
public void printAppName() {
System.out.println(appName);
}
}
6 .控制反转、AOP、自动配置之间的关联
之前的文章里专门说过AOP和自动配置,控制反转(IoC)、面向切面编程(AOP)和自动配置三者在 Spring 框架中是密切相关的,它们共同作用于简化开发、提高代码解耦性和可扩展性。在日常应用中可能会有小伙伴搞不清他们之间的关联,这里说明一下
6.1 复习一下三个概念
控制反转(IoC)
控制反转是 Spring 框架的核心机制,它使得应用中的对象(如服务、控制器等)不再由开发者手动创建和管理,而是交由 Spring 容器来进行管理。Spring IoC 容器负责对象的实例化、配置、依赖注入等操作。这样可以让开发者更专注于业务逻辑,而不必关注对象的生命周期和依赖关系。
面向切面编程(AOP)
AOP 是一种编程范式,它通过将横切关注点(如日志、事务管理、安全性等)提取到单独的模块中,来提高代码的可维护性和可重用性。在 Spring 中,AOP 是通过 IoC 容器提供的代理机制来实现的。Spring 会为带有 AOP 切面的 Bean 创建代理对象,这些代理对象会在方法执行前后插入切面逻辑。
更多信息可以参考我之前的文章:SpringBoot中AOP(面向切面编程)你真的应该知道这些
自动配置
自动配置是 Spring Boot 的一个关键特性,旨在简化 Spring 应用的配置过程。通过自动配置,Spring Boot 可以根据类路径中的依赖自动配置应用所需的组件。开发者无需手动编写复杂的配置类,Spring Boot 会自动推测并提供默认配置。
更多内容可以参考我之前的文章:SpringBoot中的自动配置(Auto Configuration)
6.2 三者之间的关系
AOP 和 IoC 的关系
- AOP 依赖于 IoC 容器来管理切面和代理对象。在 Spring 中,AOP 是通过动态代理来实现的,代理对象的创建和管理都是由 IoC 容器来控制的。切面中的逻辑(例如事务管理、日志记录等)通过代理对象插入到目标方法的前后,因此 AOP 的实现必须依赖于 IoC 容器提供的动态代理功能。
IoC 和 自动配置的关系
- 自动配置的实现依赖于 IoC 容器,自动配置会根据类路径中的库以及应用的上下文来判断需要哪些 Bean,并通过 IoC 容器将它们实例化、注入和配置。因此,自动配置本质上是 IoC 的一种自动化形式,简化了 Spring 应用的配置工作。
AOP 和 自动配置的关系
- 自动配置可以与 AOP 结合使用。在 Spring Boot 中,很多自动配置都涉及到 AOP。例如,事务管理的自动配置通常会涉及到事务切面,Spring Boot 会自动配置相应的 AOP 切面,来实现对事务的管理,而开发者不需要显式地配置 AOP。Spring Boot 会根据你项目中引入的相关依赖(如数据库相关的依赖)自动启用相关的 AOP 配置。
IoC 、AOP 、 自动配置的协作
-
自动配置和 IoC 协作:Spring Boot 的自动配置功能是通过 Spring IoC 容器来管理应用中的 Bean。自动配置通过扫描类路径中的依赖,根据当前应用的上下文条件自动创建和配置 Bean,这些 Bean 由 IoC 容器管理。
-
AOP 和 IoC 协作:AOP 切面逻辑通过 IoC 容器管理的 Bean 被动态代理。当调用方法时,AOP 会插入额外的处理逻辑(如日志、事务等),而这些都通过 IoC 容器来控制。
-
AOP 与自动配置的协作:Spring Boot 自动配置中的很多功能,特别是与跨切功能相关的配置(如事务管理、缓存等),通常会自动启用 AOP 切面。例如,当你使用 Spring Boot 的数据库连接时,Spring 会自动配置事务管理并插入 AOP 切面来处理事务的开始、提交或回滚。
举例一:自动配置和 AOP 的结合
假设你使用了 Spring Boot 和 JPA 来管理数据库操作,Spring Boot 会自动配置数据源和事务管理器。在这种情况下,Spring Boot 还会自动为事务管理启用 AOP,确保每个数据库操作都能在事务内执行,并自动处理事务的提交和回滚。开发者无需手动配置 AOP 和事务管理,Spring Boot 会自动为你配置。
举例二:AOP 与 IoC 的结合举例
假设我们需要给某个服务添加日志记录功能,可以通过 AOP 来实现。在这种情况下,IoC 管理的 Bean 通过 AOP 切面在方法调用前后自动插入日志记录代码。
创建切面
首先,定义一个日志切面来记录方法执行的情况:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBeforeMethod(JoinPoint joinPoint) {
System.out.println("Method " + joinPoint.getSignature().getName() + " is about to execute");
}
@After("execution(* com.example.service.*.*(..))")
public void logAfterMethod(JoinPoint joinPoint) {
System.out.println("Method " + joinPoint.getSignature().getName() + " has executed");
}
}
定义服务类
假设有一个简单的服务类 MyService,在这个类中,我们需要自动记录日志:
java
@Service
public class MyService {
public void performAction() {
System.out.println("Action performed.");
}
}
启用 AOP 支持
在 Spring Boot 中,可以通过 @EnableAspectJAutoProxy 注解启用 AOP 支持:
java
@SpringBootApplication
@EnableAspectJAutoProxy
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
小结:三者的关系你可以看这个
- 控制反转(IoC) 是所有功能的基础,它负责管理对象的生命周期、依赖关系和资源。
- 面向切面编程(AOP) 则通过 IoC 容器提供的代理机制实现横切关注点的处理,如日志、事务等,提升了代码的解耦性和可维护性。
- 自动配置 是 Spring Boot 提供的简化配置的机制,它依赖 IoC 容器自动配置应用中的 Bean,并与 AOP 协同工作,自动启用相关功能(如事务管理)。
7. 写在最后
控制反转(IoC)是 Spring 框架的核心思想,它帮助开发者解耦不同模块的依赖关系,提高代码的可维护性、可测试性和可扩展性。Spring Boot 通过自动配置和组件扫描,使得 IoC 的应用更加简单和高效。
通过依赖注入,开发者可以将应用中的各个组件及其依赖交给 Spring IoC 容器管理,而无需手动创建对象。Spring Boot 提供了方便的注解和配置方式来实现 IoC,使得开发者能够专注于业务逻辑,而无需关心对象创建和生命周期管理。
更多推荐


所有评论(0)