云计算百科
云计算领域专业知识百科平台

《Java 100 天进阶之路》第73篇:Spring IoC容器(2026版)

第73篇:Spring IoC容器(2026版)

📌 系列导航:《Java 100 天进阶之路》完整目录 | ⬅️ 上一篇:第72篇:JavaWeb面试高频题 | ➡️ 下一篇:第74篇:Bean生命周期(待发布)

🗺️ 本文阅读地图(3 分钟速览)

第72篇完成了JavaWeb专题的收官,本篇正式开启 Spring全家桶专题。Spring是Java后端开发的事实标准,而IoC容器是Spring最核心的基石——理解了IoC容器,就理解了Spring的"心脏":

模块核心问题一句话回答
IoC是什么 控制反转到底反转了什么? 对象的创建权从"自己new"反转给"容器管理"
DI是什么 依赖注入和IoC什么关系? DI是IoC的具体实现方式——容器把依赖"注入"给对象
BeanFactory vs ApplicationContext 两个容器有什么区别? BeanFactory是"基础款"(懒加载),ApplicationContext是"旗舰款"(预加载+企业级功能)
Bean是什么 Spring里的Bean到底是什么? 被Spring IoC容器管理的Java对象
Bean生命周期 Bean从生到死经历什么? 实例化→属性填充→初始化→使用→销毁
三种配置方式 怎么告诉Spring要管理哪些对象? XML配置、注解配置、Java配置(@Configuration + @Bean)
面试最爱问 高频考点有哪些? 见文末 🎤 小节

一、核心知识点

1. IoC是什么?

IoC(Inversion of Control,控制反转)是一种设计原则,用于减少代码间的直接依赖关系。其核心思想是:将对象的创建、依赖管理等控制权从业务代码转移到外部容器。

💡 通俗理解:传统编程中,调用者主动创建和管理被调用者的生命周期——你需要什么,自己new一个。IoC模式下,你只需要声明"我需要什么",容器会帮你创建好并"注入"进来。

2. DI是什么?

DI(Dependency Injection,依赖注入)是IoC的具体实现方式。对象只通过构造函数参数、工厂方法参数或属性来定义它们的依赖项,容器在创建Bean时注入这些依赖。

💡 核心关系:IoC是一种思想,DI是实现这种思想的技术手段。

3. IoC解决了什么问题?

问题传统方式IoC方式
耦合度高 类内部直接new依赖对象,换实现要改代码 依赖通过构造函数/Setter传入,换实现不改代码
难以测试 依赖硬编码,无法Mock 依赖可替换,单元测试容易
难以扩展 新增功能要改已有代码 通过配置/注解扩展,符合开闭原则

4. IoC的三大优势

优势说明
解耦性 对象间的依赖关系通过容器配置而非硬编码实现
可测试性 依赖注入使得单元测试可以通过Mock对象轻松完成
可配置性 Bean的创建和装配过程可以通过配置文件或注解灵活调整

二、通俗讲解(1分钟开心学)

把IoC容器想象成"智能工厂 + 配送中心"

本系列第68篇讲过,Servlet容器(Tomcat)是"后厨"。Spring IoC容器比它更进了一步——它不只是"后厨",而是整条供应链的智能管理中心。

  • 传统方式(自己new) :你想做一道菜,得自己种菜、自己养猪、自己磨调料——所有依赖都得自己搞定。
  • IoC方式(容器管理) :你只需要告诉工厂"我要做宫保鸡丁",工厂自动把鸡肉、花生、干辣椒配齐送到你手上——你只管炒菜。

两个容器的比喻:

  • BeanFactory:小区楼下的自动售货机——你要什么,投币才出货(懒加载),功能单一。
  • ApplicationContext:大型仓储超市——一开门就把所有货品都摆好(预加载),还提供推车、导购、退换货等全套服务(事件、国际化、AOP等)。

三、Spring IoC容器体系

3.1 容器层级关系

Spring的IoC容器以 BeanFactory 为顶层接口,ApplicationContext 是其子接口:

在这里插入图片描述

org.springframework.beans 和 org.springframework.context 包是Spring Framework IoC容器的基础。

3.2 BeanFactory vs ApplicationContext

这是Spring面试100%会问的对比题。

对比维度BeanFactoryApplicationContext
官方定位 最基础的IoC容器接口,定义Bean管理的核心规范 BeanFactory的子接口,增加了企业级功能
加载策略 懒加载——调用getBean()时才创建实例 预加载——启动时一次性创建所有单例Bean
核心功能 只提供getBean()等基础功能 继承BeanFactory全部功能 + 10大扩展功能
实际使用 几乎见不到 每天都用——SpringApplication.run(…)返回的就是它
常用实现 DefaultListableBeanFactory AnnotationConfigApplicationContext、ClassPathXmlApplicationContext

ApplicationContext比BeanFactory多出的核心功能:

功能说明
事件发布与监听 ApplicationEvent + @EventListener
国际化(i18n) MessageSource支持多语言
资源加载 ResourceLoader支持classpath:、file:等
环境抽象 Environment + @Profile支持多环境配置
AOP自动代理 自动识别@Aspect并织入,@Transactional直接生效
Web应用支持 WebApplicationContext

💡 记忆口诀:BeanFactory是"基础款"(够用但简陋),ApplicationContext是"旗舰款"(功能全、体验好) 。实际项目100%用ApplicationContext。

3.3 Bean是什么?

在Spring中,构成应用程序骨架并由Spring IoC容器管理的对象称为Bean。Bean是由Spring IoC容器实例化、组装和管理的对象。

💡 本质:Bean就是一个普通的Java对象,唯一特殊之处在于——它由Spring容器管理,而不是你自己new出来的。

四、Bean生命周期(5阶段)

Bean的生命周期是Spring面试的必考项,需要掌握以下核心阶段:

在这里插入图片描述

初始化阶段详解(这是生命周期中最复杂的阶段):

步骤说明
① Aware接口回调 BeanNameAware、BeanFactoryAware等
② BeanPostProcessor前置处理 初始化前的拦截
③ InitializingBean.afterPropertiesSet() 接口方式初始化
④ 自定义init-method XML或注解指定的初始化方法
⑤ BeanPostProcessor后置处理 初始化后的拦截,AOP代理在此完成

五、三种Bean配置方式

容器通过读取配置元数据来获取指令——告诉它要实例化哪些对象、如何装配它们。配置元数据可以用三种方式表达:

5.1 XML配置(传统方式)

<!– applicationContext.xml –>
<beans>
<bean id="userService" class="com.example.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.example.UserDaoImpl"/>
</beans>

// 加载XML配置
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = ctx.getBean("userService", UserService.class);

5.2 注解配置(主流方式)

@Service // 声明为业务层Bean
public class UserServiceImpl implements UserService {
@Autowired // 自动注入依赖
private UserDao userDao;
}

@Repository // 声明为数据访问层Bean
public class UserDaoImpl implements UserDao {
// 数据访问逻辑
}

// 启动容器(Spring Boot自动完成)
ApplicationContext ctx = new AnnotationConfigApplicationContext("com.example");

💡 注解含义:@Component 是通用注解,@Service、@Repository、@Controller 是其特化版本,分别用于业务层、数据层和控制层。

5.3 Java配置(@Configuration + @Bean)

@Configuration // 声明这是一个配置类
public class AppConfig {

@Bean // 方法返回值会被注册为Spring容器中的Bean
public UserService userService(UserDao userDao) {
return new UserServiceImpl(userDao);
}

@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
}

// 加载Java配置
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

💡 @Configuration原理:配置类会经过ConfigurationClassPostProcessor(后置处理器)处理,解析所有@Bean方法并转换为Bean定义。@Configuration类本身也会被注册为容器中的一个Bean。

六、避坑要点

错误/误区后果正确做法
混淆IoC和DI的概念 面试答非所问 IoC是思想,DI是实现方式
认为new出来的对象也是Bean 容器无法管理,依赖注入失效 只有容器创建和管理的对象才是Bean
误以为项目用的是BeanFactory 对容器能力理解有偏差 实际项目100%用ApplicationContext
不知道@Configuration和@Component的区别 配置类被代理,行为异常 @Configuration是配置类(Full模式),@Component是普通组件
在Bean的构造函数中做耗时操作 容器启动变慢 耗时操作放到@PostConstruct或afterPropertiesSet中

七、面试高频考点

Q1:IoC和DI是什么关系?

IoC(控制反转)是一种设计思想——将对象的创建和依赖管理的控制权从代码转移到容器。DI(依赖注入)是IoC的具体实现方式——对象通过构造函数参数、工厂方法参数或属性来定义依赖,容器在创建Bean时注入这些依赖。IoC是"理念",DI是"做法" 。

Q2:BeanFactory和ApplicationContext的区别?

BeanFactory是Spring最基础的IoC容器接口,采用懒加载策略,只提供getBean()等基础功能。ApplicationContext是BeanFactory的子接口,采用预加载策略——启动时一次性创建所有单例Bean,还额外提供了事件发布、国际化、资源加载、AOP集成等企业级功能。实际项目100%用ApplicationContext。

Q3:Spring Bean的生命周期有哪些阶段?

五个阶段:①实例化——容器通过反射调用构造函数创建实例;②属性填充——通过依赖注入设置属性值;③初始化——执行Aware回调、BeanPostProcessor前置处理、afterPropertiesSet、自定义init-method、BeanPostProcessor后置处理;④使用——Bean被应用程序调用;⑤销毁——容器关闭时按相反顺序触发销毁逻辑。

Q4:@Configuration和@Bean的作用是什么?

@Configuration标记在类上,声明这是一个配置类,相当于XML配置文件。@Bean标记在配置类的方法上,指示该方法返回的对象应该被注册为Spring容器中的Bean。配置类会经过ConfigurationClassPostProcessor处理,将@Bean方法转换为Bean定义。

Q5:Spring支持哪几种Bean配置方式?

三种:①XML配置——传统的<bean>标签方式;②注解配置——通过@Component、@Service、@Autowired等注解;③Java配置——通过@Configuration + @Bean。现代Spring Boot项目以注解配置和Java配置为主。

🎤 面试官追问陷阱(加分题)

追问1:“@Configuration标注的类和@Component标注的类有什么区别?”

👉 @Configuration类会被Spring动态代理,保证其中@Bean方法调用时返回的是容器中已存在的Bean实例(保证单例)。而@Component标注的普通类不会被代理。简单说:@Configuration是"Full模式"(Bean之间调用走代理),@Component是"Lite模式"(不走代理) 。

追问2:“ApplicationContext启动时做了什么事?能简单说下流程吗?”

👉 核心是refresh()方法。主要步骤:①创建并准备BeanFactory;②读取配置元数据(XML/注解/Java配置),生成BeanDefinition;③注册BeanPostProcessor;④初始化所有非懒加载的单例Bean;⑤发布上下文就绪事件。这就是为什么ApplicationContext启动比BeanFactory慢——它把活都提前干完了。

八、练习题

  • 简答题:请用自己的话解释IoC和DI的关系。

  • 代码题:使用@Configuration + @Bean方式,配置一个DataSource Bean和一个UserDao Bean,UserDao依赖DataSource。

  • 分析题:某Spring Boot项目启动非常慢,经排查发现启动时创建了大量Bean。请分析可能的原因,并给出优化建议。

  • 📊 你的学习进度

    • 当前:第73篇 / 共108篇 · 进阶篇:Spring全家桶(第73~82篇)
    • ✅ 已完成:基础篇44篇 + 第45~73篇
    • 📖 正在学:第73篇
    • ⏳ 待学习:第74~108篇

    👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇

    👉 下一篇文章预告

    🚀 下一篇:《第74篇:Bean生命周期》

    内容简介:Bean生命周期完整15步详解、BeanPostProcessor原理、InitializingBean与@PostConstruct执行顺序、销毁流程、扩展点实战。

    👉 Spring全家桶专题持续推进,深入Bean生命周期!

    📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer! 👉 点击关注我,更新后第一时间收到推送!

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 《Java 100 天进阶之路》第73篇:Spring IoC容器(2026版)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!