⚡ 用药Ai助手 生成时间:2026-04-09 094227(北京时间)

小编头像

小编

管理员

发布于:2026年04月29日

11 阅读 · 0 评论


🏆 用药Ai助手:2026年Spring IoC与DI从入门到面试全链路解析

Spring IoC(控制反转)与DI(依赖注入)是Java企业级开发中必学必会的核心知识点。很多开发者能熟练使用 @Autowired 注解,却讲不清“IoC和DI到底是什么关系”,面试时一开口就卡壳——这就是典型的“会用但不懂原理”。本文将带你彻底理清这两个核心概念,从传统代码痛点出发,一步步深入到底层原理,配以极简代码示例和高频面试题,助你建立完整的知识链路。

一、痛点切入:为什么需要IoC和DI?

传统方式:在类内部直接 new 依赖对象。

java
复制
下载
public class UserService {
    private UserDao userDao = new UserDaoImpl();  // 硬编码依赖
    public void doSomething() {
        userDao.save();
    }
}

三个致命缺陷

  1. 高耦合UserServiceUserDaoImpl 紧耦合,无法替换实现类;

  2. 难测试:无法用Mock对象替换真实 UserDao 进行单元测试;

  3. 不易扩展:若 UserDaoImpl 构造方法新增参数,所有使用它的类都要改。

有了IoC容器,Spring接管了对象的创建和生命周期管理,开发者只需声明“我需要什么”,容器主动把依赖“送过来”——这就是DI的本质。

二、IoC(控制反转):一种颠覆性的设计思想

定义:IoC全称 Inversion of Control(控制反转) ,是一种高层设计思想,指将对象的创建权、依赖管理权和生命周期控制权从应用程序代码转移到外部容器-1

一句话理解:传统方式是“我要用什么,我自己创建”(正转);IoC是“我需要什么,容器给我”(反转)。控制权从代码移交给了容器-1

生活类比:传统方式像自己下厨——要亲自买菜、洗菜、做菜(手动 new 对象);IoC像请了个管家——你只需告诉管家“我中午要吃三菜一汤”,管家会包揽一切采购和烹饪-9

三、DI(依赖注入):IoC思想的具体落地

定义:DI全称 Dependency Injection(依赖注入) ,是IoC思想最典型的技术实现手段,聚焦于“如何把依赖对象传递给目标对象”-1

三种注入方式

方式代码示例适用场景
构造器注入@Autowired public UserService(UserDao dao) { this.dao = dao; }推荐,依赖不可变,便于单元测试
Setter注入@Autowired public void setUserDao(UserDao dao) { this.dao = dao; }可选依赖,可后续修改
字段注入@Autowired private UserDao dao;最简洁,但不易测试,Spring官方不推荐

注意:若类只有一个构造方法,@Autowired 可省略;若有多个构造方法,必须用 @Autowired 明确指定-25

四、IoC与DI:思想 vs 实现

对比维度IoC(控制反转)DI(依赖注入)
抽象层次设计思想(Why)技术实现(How)
核心问题谁来控制?怎么传递依赖?
能否独立存在可以,如通过JNDI实现必须依附于IoC,否则只是普通传值
与Spring的关系Spring的核心设计理念Spring实现IoC的核心手段

一句话总结IoC是“目标”,DI是“手段”——IoC回答“谁控制”,DI回答“如何传”,二者维度不同,不可互换-1

五、代码示例:对比传统方式与IoC+DI

场景OrderService 依赖 OrderDao

方式一:传统方式(高耦合)

java
复制
下载
public class OrderService {
    private OrderDao orderDao = new OrderDaoImpl();  // 硬编码
    public void createOrder() {
        orderDao.save();
    }
}

方式二:IoC + DI(Spring方式)

java
复制
下载
@Service                     // 告诉Spring:请管理我
public class OrderService {
    private final OrderDao orderDao;
    
    @Autowired               // 告诉Spring:请帮我注入依赖
    public OrderService(OrderDao orderDao) {
        this.orderDao = orderDao;
    }
    
    public void createOrder() {
        orderDao.save();
    }
}

执行流程

  1. Spring启动时扫描带 @Service@Component 等注解的类,封装成 BeanDefinition

  2. 容器创建 OrderService 实例,发现构造方法需要 OrderDao

  3. 容器检查 OrderDao 是否已存在(如有 @Repository 注解,已被注册为Bean);

  4. 容器通过反射调用构造方法,将 OrderDao 实例注入;

  5. 最终返回可直接使用的 OrderService 对象-3

六、底层原理:Spring是如何做到的?

Spring IoC容器的底层实现依赖两大核心技术:反射设计模式-30

6.1 核心接口体系

java
复制
下载
BeanFactory (最底层)ApplicationContext (增强版,日常开发使用)
  • BeanFactory:基础接口,定义 getBean() 等核心方法,懒加载(调用时才创建Bean);

  • ApplicationContext:继承 BeanFactory,扩展国际化、事件发布、资源加载等企业级功能,非懒加载(启动时创建所有单例Bean)-30

6.2 核心执行流程

text
复制
下载
1. 容器初始化 → 2. 扫描注解/配置 → 3. 封装BeanDefinition → 4. 实例化Bean → 5. 依赖注入 → 6. 初始化回调 → 7. 使用 → 8. 销毁

关键技术点

  • 反射:通过类的全限定名动态创建对象,无需 new 关键字;

  • 三级缓存:解决循环依赖问题,核心是 singletonObjectsearlySingletonObjectssingletonFactories 三个Map-

  • 设计模式:工厂模式(创建Bean)、模板方法(生命周期钩子)、策略模式(多种注入方式)等-

注意:只有被Spring容器管理的对象才称为Bean。手动 new 出来的对象,即使类型相同,也不会被 @Autowired 注入,也无法被AOP拦截-31

七、高频面试题与参考答案

Q1:请解释什么是IoC?什么是DI?两者的关系是什么?

标准回答

  • IoC(控制反转) 是一种设计思想,指将对象的创建、依赖管理和生命周期控制权从程序代码转移到外部容器;

  • DI(依赖注入) 是实现IoC的具体技术手段,指容器在创建对象时自动将依赖对象“注入”给目标对象;

  • 关系:IoC是思想(目标),DI是手段(实现)。IoC回答“谁来控制”,DI回答“怎么传递”,二者不可互换-15

踩分点:思想 vs 实现、控制权反转、依赖传递、@Autowired。


Q2:Spring中的Bean默认是单例还是多例?生命周期是怎样的?

标准回答

  • Spring Bean默认是单例singleton),即整个IoC容器中只存在一个实例-15

  • 单例Bean的生命周期:实例化 → 属性填充(依赖注入)→ 初始化(@PostConstruct)→ 使用 → 销毁(@PreDestroy);

  • 可通过 @Scope 设置为 prototype(原型)、requestsession-2

踩分点:singleton、生命周期阶段、@Scope、prototype。


Q3:@Autowired和@Resource有什么区别?

标准回答

对比项@Autowired(Spring原生)@Resource(JSR-250标准)
注入规则默认按类型(byType)默认按名称(byName)
多实现类处理需配合 @Qualifier 指定可按名称精确匹配
所属规范Spring专有Java标准(更通用)

当接口有多个实现类时,@Autowired 必须加 @Qualifier 指定具体Bean名,否则启动报错-31

踩分点:byType vs byName、@Qualifier、多实现类冲突解决。


Q4:Spring如何解决循环依赖问题?

标准回答

  • Spring通过三级缓存机制解决单例Bean之间的循环依赖;

  • 三级缓存包括:singletonObjects(一级,已完成初始化的单例池)、earlySingletonObjects(二级,提前暴露的早期Bean)、singletonFactories(三级,Bean工厂缓存);

  • 但以下情况无法解决:构造器注入的循环依赖、prototype作用域的Bean、涉及AOP代理的复杂循环-31

踩分点:三级缓存、singletonObjects、earlySingletonObjects、singletonFactories、构造器注入不可解。


Q5:Spring IoC容器的核心实现原理是什么?

标准回答

  • 底层技术:反射 + 设计模式(工厂、模板方法、策略);

  • 核心流程:扫描配置/注解 → 封装为 BeanDefinition → 注册到 BeanDefinitionRegistry → 通过反射实例化 → 属性填充(DI)→ 初始化回调;

  • 两大核心接口BeanFactory(基础,懒加载)和 ApplicationContext(增强,非懒加载,日常开发用)-30

踩分点:反射、BeanDefinition、ApplicationContext vs BeanFactory、生命周期流程。

八、结尾总结

本文核心知识点回顾:

核心概念一句话总结
IoC(控制反转)一种设计思想:对象的创建权交给容器
DI(依赖注入)一种技术实现:容器主动“送”依赖
两者关系IoC是思想(目标),DI是手段(实现),不可互换
底层原理反射 + 设计模式 + BeanDefinition + 三级缓存
面试高频点默认单例、@Autowired vs @Resource、循环依赖的三级缓存

重点提醒:面试时别只说“IoC是控制反转”就结束——要完整说出“这是一种设计思想,将对象创建权交给容器,DI是其具体实现手段,通过构造器/Setter/@Autowired等方式注入-19

后续将深入讲解 Spring AOP(面向切面编程) 的实现原理与动态代理机制,敬请期待!


本文由「用药Ai助手」智能生成,致力于用最易懂的方式讲透技术原理。欢迎收藏、转发、讨论~

标签:

相关阅读