Spring的IOC详解

IOC=控制反转(思想),把「创建对象、管理依赖」的控制权,从程序员手里,交给容器。容器解决了"对象管理"问题。不用自己 new 对象了

DI=依赖注入(实现IOC的手段),实现分为:构造器注入、setter()注入、接口注入三种,将对象需要的依赖传递给它,而不是让对象自行创建依赖

Spring官方推荐

Spring团队明确推荐使用构造器注入,主要原因:

  1. 确保依赖不可变:final关键字保证
  2. 确保对象完全初始化:构造完成后就可使用
  3. 避免空指针异常:依赖不可能为null
  4. 更好的可测试性:构造时就确定所有依赖
  5. 非强制加final关键字,官方推荐规范加final

注入方式示例

1、构造器注入

复制代码
/**
 * 用户 Controller
 */
@RestController
@RequestMapping("/")
public class UserController {

    // 1. 定义 private final
    private final UserService userService;

    /**
     * 构造器注入
     * 2. 只有一个构造器,Spring 自动注入,不用 @Autowired
     */
    public UserController(UserService userService) {
        this.userService = userService;
    }
}

lombok简化版@RequiredArgsConstructor:自动给所有 final 字段生成构造器\Spring 自动识别注入\ 不需要写任何构造器

复制代码
/**
 * 用户 Controller
 */
@RestController
@RequestMapping("/")
@RequiredArgsConstructor    // 关键
public class UserController {

    private final UserService userService;
}

2、setter()注入

Setter 注入是通过类的 setter 方法来注入依赖,需要配合@Autowired注解使用(Spring 4.3+ 也可使用@RequiredArgsConstructor,但手动写 setter 更直观)。

复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller // 补充Controller注解,确保Spring能扫描到该类
public class UserController {

    // 1. 仅定义私有变量,去掉final(setter注入不能用final,因为final变量必须在构造器/声明时赋值)
    private UserService userService;

    /**
     * Setter注入
     * 2. 通过setter方法注入依赖,必须加@Autowired注解
     */
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

3、字段注入

字段注入是直接在类的成员变量上标注@Autowired,无需构造器或 setter 方法,是最简洁的写法,但也是 Spring 官方不推荐的写法(不利于单元测试)。

复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {

    // 1. 直接在字段上标注@Autowired,无需构造器/setter
    @Autowired
    private UserService userService; // 同样不能用final
}

可选依赖和必选依赖判断标准(核心看「这个依赖缺失时,你的类 / 功能是否还能正常工作」------ 这不是技术规则,而是业务逻辑和功能设计决定)

|------|-------------------------|---------------------|
| 类型 | 核心特征 | 典型场景 |
| 必选依赖 | 依赖缺失 → 类无法初始化 / 功能完全不可用 | 数据库 DAO、核心业务服务、配置中心 |
| 可选依赖 | 依赖缺失 → 类能正常工作,仅部分功能降级 | 缓存服务、日志增强、消息通知 |


IOC不是管理所有对象,只管【Bean】

✅ Spring IoC 容器 管:

被你加上这些注解的类:

  • @Controller------ 控制层
  • @Service------ 业务层
  • @Repository------ 数据层(Dao、Mapper)
  • @Component ------ 通用组件(工具类、配置类、自定义组件等)
  • @Configuration 配置类
  • @Bean 方法返回的对象

这些叫 Bean,Spring 负责创建、注入、销毁。


❌ Spring IoC 容器 不管:

  • 实体类(User、Order、Product...)
  • VO / DTO / BO / POJO
  • 普通工具类对象
  • 方法内部临时创建的对象
  • new 出来的一切普通对象

这些不是 Bean,Spring 不负责,必须你自己 new。


相关推荐
SL_staff1 小时前
制造业订单交付崩盘?用四层协同框架重建交付可信度(技术实践)
java·产品·全栈
AI源码1 小时前
基于 Python 的短视频用户行为分析系统
开发语言·python
旖旎夜光2 小时前
【C++ 基础入门】类和对象(上):封装、对象模型与 this 指针
开发语言·c++·笔记·学习
SL_staff2 小时前
打破风控迭代死循环:用决策编排重构业务与技术协作链路
java·产品·全栈
揽星河..2 小时前
【C语言】结构体
c语言·开发语言
2601_966949653 小时前
如何封装 qd.klines.batch(),让批量 K 线查询函数在多个策略中复用?
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
Mikko73 小时前
Redis 连接数满了服务端有错误信息吗?连接数不增加却命令超时?6.2 实测连接池、超时与大 key 怎么判定
java·spring boot·redis·后端
.Bryce.3 小时前
从零到一开发技术名词大全:从需求分析到 AI Agent 工程
java·网络·人工智能·agent·需求分析·agent评测
SL_staff3 小时前
JVS-APS的7个刚性约束设计:从无限产能幻觉到可执行排产的工程实践
java·spring cloud·全栈
神仙别闹4 小时前
基于Python实现英词语自动对齐系统
开发语言·python