【Spring 核心: IoC&DI】从原理到注解使用、注入方式全攻略

Spring 核心:IoC & DI 从原理到注解使用、注入方式全攻略(2026 最新版)

Spring 框架最核心、最闪耀的部分就是 IoC(Inversion of Control,控制反转)DI(Dependency Injection,依赖注入)。它们是 Spring 实现“低耦合、高可维护、可测试”代码的基石。掌握 IoC & DI,你就真正掌握了 Spring 的灵魂。

1. IoC 与 DI 的核心概念与原理

IoC(控制反转)
传统方式:程序主动创建依赖对象(new)。
Spring 方式:控制权反转给容器,由 Spring IoC 容器负责对象的创建、装配和管理。

DI(依赖注入)
IoC 的具体实现方式:容器在创建对象时,自动将它所依赖的对象“注入”进来。

经典比喻

  • 传统:你饿了自己去厨房做饭(主动 new 依赖)。
  • Spring:你坐在餐厅,服务员(IoC 容器)把菜(依赖对象)端给你(DI)。

IoC 容器做了什么?

  1. 创建对象(Bean)
  2. 管理对象生命周期(singleton/prototype 等)
  3. 装配对象之间的依赖关系
  4. 提供查找、AOP、事务等高级功能

2. Spring IoC 容器的两种主要实现

容器类型接口/类特点使用场景
BeanFactoryorg.springframework.beans.factory.BeanFactory基础容器,提供最基本的 IoC 功能资源极度受限的环境
ApplicationContextorg.springframework.context.ApplicationContextBeanFactory 的子接口,扩展了国际化、事件发布、AOP 等几乎所有项目都用这个

常用实现类:

  • AnnotationConfigApplicationContext(注解配置,推荐)
  • ClassPathXmlApplicationContext(XML 配置,已过时)

3. 依赖注入的三种方式(重点掌握)

Spring 支持三种注入方式,推荐优先级:构造器 > Setter > 字段

注入方式实现方式推荐度优点缺点示例代码
构造器注入通过构造函数参数注入★★★★★依赖强制、不可变、便于测试、支持循环依赖解决参数多时构造函数臃肿最推荐
Setter 注入通过 setter 方法注入★★★☆☆支持可选依赖、灵活依赖可变、运行时可能被修改适合可选依赖
字段注入直接 @Autowired 到字段★☆☆☆☆代码简洁隐藏依赖、难以单元测试、违反封装原则不推荐

构造器注入示例(推荐写法)

@Service
public class UserService {
    private final UserRepository userRepository;

    // Spring Boot 3 + 单构造器可省略 @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void save(User user) {
        userRepository.save(user);
    }
}

Setter 注入示例

@Service
public class EmailService {
    private MailSender mailSender;

    @Autowired
    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }
}

字段注入示例(不推荐)

@Service
public class OrderService {
    @Autowired
    private PaymentService paymentService;  // 隐藏依赖,测试麻烦
}

4. 注解驱动的 IoC & DI(现代 Spring 主流方式)

Spring 4+ 推荐完全基于注解配置,XML 已基本淘汰。

核心注解一览表

注解作用位置功能示例
@Component标记为 Spring 管理的 Bean(通用)@Component public class MyService {}
@Service服务层类@Component 的语义化别名业务逻辑层
@Repository持久层类@Component + 异常翻译(持久层异常转 Spring 异常)DAO/Repository
@ControllerWeb 层类@Component + MVC 支持传统 MVC
@RestControllerREST API 类@Controller + @ResponseBody返回 JSON
@Configuration配置类标记为配置类,通常配合 @Bean替代 XML 配置
@Bean方法方法返回值作为 Bean 交给容器管理第三方类无法加 @Component 时使用

组件扫描

@SpringBootApplication  // 包含 @ComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

默认扫描主类同包及其子包下的组件。

@Autowired 注入注解

注解作用位置功能
@Autowired字段、构造器、Setter按类型自动注入(byType)
@Qualifier与 @Autowired 配合指定 Bean 名称注入(解决同类型多个 Bean)
@Primary类上同类型多个 Bean 时优先注入此 Bean
@Resource字段、SetterJSR-250 注解,按名称注入(byName)
@Inject字段、构造器、SetterJSR-330 标准注解,按类型注入

解决同类型多个 Bean 示例

// 方案1:@Primary
@Primary
@Repository
public class MySqlUserDao implements UserDao {}

// 方案2:@Qualifier
@Autowired
@Qualifier("mySqlUserDao")
private UserDao userDao;

5. Bean 的作用域(Scope)

作用域注解/配置说明
singleton默认 / @Scope(“singleton”)容器中只有一个实例(最常用)
prototype@Scope(“prototype”)每次注入或获取都创建新实例
request@Scope(“request”)Web 项目中,每个 HTTP 请求一个实例
session@Scope(“session”)每个 HTTP Session 一个实例

6. 生命周期回调

@Component
public class MyBean implements InitializingBean, DisposableBean {

    @PostConstruct  // 初始化后调用(推荐)
    public void init() {
        System.out.println("Bean 初始化完成");
    }

    @PreDestroy     // 销毁前调用(推荐)
    public void destroy() {
        System.out.println("Bean 即将销毁");
    }

    @Override
    public void afterPropertiesSet() throws Exception { /* InitializingBean */ }

    @Override
    public void destroy() throws Exception { /* DisposableBean */ }
}

7. 最佳实践总结

建议原因
优先使用构造器注入依赖明确、对象不可变、支持循环依赖
接口编程 + DI松耦合,便于测试和切换实现
避免字段注入隐藏依赖、难以单元测试
使用 @Primary 或 @Qualifier优雅解决同类型 Bean 冲突
配置类用 @Configuration + @Bean管理第三方库 Bean
Lombok @RequiredArgsConstructor简化构造器注入代码

Lombok 优化示例

@Service
@RequiredArgsConstructor  // 自动生成含 final 字段的构造器
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;
}

8. 一句话总结

IoC 是设计思想:控制权从代码交给容器。
DI 是实现手段:容器把依赖“注入”给对象。
注解 + 构造器注入 是现代 Spring 的最佳实践。

掌握了 IoC & DI,你就拥有了编写优雅、可维护 Spring 应用的超级能力!

如果想深入探讨循环依赖原理、@Configuration 代理机制、手写简易 IoC 容器,或者结合 Spring Boot 的自动配置源码分析,随时告诉我,我继续带你飞!🚀

文章已创建 3707

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部