Spring Boot3 IOC 项目地址
https://gitee.com/supervol/loong-springboot-study
(记得给个start,感谢)
IOC 概述
在 Spring Boot 3 中,IOC(Inversion of Control,控制反转)是核心思想之一,它彻底改变了传统 Java 开发中对象创建和依赖管理的方式,极大地降低了代码耦合度,提升了系统的可维护性和扩展性。
IOC 核心概念
IOC 的本质是将对象的创建权、依赖关系的管理交给 Spring 容器,而非由开发者在代码中手动 new 对象或维护依赖。这种 "反转" 体现在:
- 传统开发:开发者主动控制对象创建(如
UserService service = new UserService()
)和依赖注入(如service.setDao(new UserDao())
)。 - IOC 模式:Spring 容器负责创建对象(Bean),并根据配置自动将依赖对象 "注入" 到目标对象中,开发者只需声明 "需要什么",无需关心 "如何获取"。
IOC 与 DI 的关系
DI(Dependency Injection,依赖注入)是 IOC 的具体实现方式。
- IOC 是思想:强调 "反转控制"(将对象管理权交给容器)。
- DI 是手段:容器通过构造器、setter 方法等方式,将依赖对象 "注入" 到目标对象中,完成依赖关系绑定。
IOC 示例
请参考项目地址中 springboot-ioc/springboot-ioc-demo 模块代码。
IOC 使用
Spring Boot 3 基于 Spring Framework 6,简化了 IOC 容器的配置(无需 XML,全注解驱动),核心步骤如下:
定义 Bean
让容器管理对象,Spring 通过注解识别需要管理的对象(Bean),常用注解:
@Component
:通用注解,标识一个类为 Spring 管理的 Bean(适用于普通组件)。@Service
:标注业务逻辑层(Service)的 Bean(语义化注解,本质是@Component
)。@Controller
:标注控制层(MVC 中的 Controller)的 Bean。@Repository
:标注数据访问层(DAO)的 Bean,还会自动处理数据库操作异常。
示例:定义 Service 层 Bean
// 业务逻辑层,@Service标识为Spring管理的Bean
@Service
public class UserService {// 后续通过DI注入依赖private final UserDao userDao;// 构造器注入(推荐)public UserService(UserDao userDao) {this.userDao = userDao;}public String getUserInfo() {return userDao.queryUser();}
}
示例:定义 DAO 层 Bean
// 数据访问层,@Repository标识为Spring管理的Bean
@Repository
public class UserDao {public String queryUser() {return "用户信息:张三";}
}
依赖注入(DI)
容器自动注入依赖,Spring 提供多种注入方式,推荐构造器注入(更符合单一职责,且避免空指针问题)。
(1)构造器注入(推荐)
通过类的构造方法,容器自动传入依赖的 Bean(如上面UserService
中注入UserDao
)。
(2)Setter 方法注入
通过 setter 方法注入依赖,需配合@Autowired
注解:
@Service
public class UserService {private UserDao userDao;// Setter注入@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}
}
(3)字段注入(不推荐)
直接在字段上使用@Autowired
注入,缺点是无法通过构造器保证依赖非空,且不利于单元测试:
@Service
public class UserService {// 字段注入(不推荐)@Autowiredprivate UserDao userDao;
}
启动容器并使用 Bean
Spring Boot 通过@SpringBootApplication
注解启动容器,该注解包含:
@ComponentScan
:自动扫描当前包及子包下的@Component
(含@Service
、@Controller
等)注解类,将其注册为 Bean。
示例:启动类与使用 Bean
// 启动类,@SpringBootApplication标识Spring Boot应用入口
@SpringBootApplication
public class IocDemoApplication {public static void main(String[] args) {// 启动Spring容器,返回ApplicationContext(容器上下文)ApplicationContext context = SpringApplication.run(IocDemoApplication.class, args);// 从容器中获取UserService BeanUserService userService = context.getBean(UserService.class);// 调用Bean的方法(依赖已由容器自动注入)System.out.println(userService.getUserInfo()); // 输出:用户信息:张三}
}
自定义 Bean
非 @Component 注解类,如果需要将第三方类(如RedisTemplate
)或未加@Component
的类注册为 Bean,可通过@Configuration
+@Bean
实现:
// 配置类,@Configuration标识为配置类
@Configuration
public class CustomConfig {// @Bean:将方法返回值注册为Spring容器中的Bean,默认名称为方法名@Beanpublic RedisUtil redisUtil() {return new RedisUtil(); // 假设RedisUtil是第三方工具类}
}// 使用自定义Bean
@Service
public class OrderService {private final RedisUtil redisUtil;// 注入自定义的RedisUtil Beanpublic OrderService(RedisUtil redisUtil) {this.redisUtil = redisUtil;}
}
Bean 的作用域
默认情况下,Spring 容器中的 Bean 是单例(singleton)(整个容器中只有一个实例)。可通过@Scope
指定其他作用域:
@Scope("prototype")
:多例,每次获取 Bean 时创建新实例。@Scope("request")
:Web 环境中,每个请求对应一个实例。@Scope("session")
:Web 环境中,每个会话对应一个实例。
示例:多例 Bean
@Service
@Scope("prototype") // 多例模式
public class CartService {// ...
}
IOC 的优势
- 解耦:对象创建与依赖管理交给容器,避免硬编码依赖(如
new UserService(new UserDao())
)。 - 可维护性:集中管理 Bean 的生命周期和依赖,修改依赖只需调整配置。
- 可测试性:便于替换依赖(如测试时用 Mock 对象替换真实 DAO)。
- 灵活性:通过作用域、懒加载等配置,灵活控制 Bean 的创建时机和生命周期。
总结
Spring Boot 3 的 IOC 通过注解驱动简化了 Bean 的定义和依赖管理,核心是 "将控制权交给容器"。实际开发中,推荐使用@Service
、@Repository
等语义化注解定义 Bean,通过构造器注入管理依赖,配合@Configuration
+@Bean
处理自定义 Bean,充分发挥 IOC 的解耦优势。