一、什么是 IOC
1. 全称
IOC = Inversion of Control,控制反转,是一种设计思想,Spring IOC 是该思想的落地容器。
2. 传统开发 vs IOC
传统开发(主动创建对象)
业务代码主动 new 依赖,控制权在开发者代码手里:
// 代码自己控制对象创建、依赖管理
UserService service = new UserServiceImpl();
UserDao dao = new UserDaoImpl();
service.setDao(dao);
问题:耦合严重、替换实现类要改代码、难以单元测试。
IOC 控制反转(容器管理对象)
对象创建、依赖装配、生命周期全部交给 IOC 容器,业务代码只使用,不负责创建。 控制权从业务代码反转到容器,因此叫控制反转。
3. DI(依赖注入)——IOC 的实现手段
IOC 是思想,DI(Dependency Injection 依赖注入)是实现 IOC 的方式: 容器自动把对象需要的依赖注入进去,无需手动 new。
二、Spring IOC 容器核心职责
- Bean 管理:实例化、缓存单例 Bean
- 依赖注入 DI:自动装配属性、构造器、接口依赖
- Bean 生命周期管理:初始化、销毁回调
- Bean 作用域:singleton /prototype/request /session 等
- 配置读取:XML、注解、JavaConfig、注解扫描
- AOP 基础支撑:容器管理 Bean 才能生成代理对象
三、IOC 容器两大核心接口
1. BeanFactory(顶层根接口)
最简单容器,懒加载:使用时才实例化 Bean,只提供基础 Bean 获取能力。
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
UserService service = (UserService) factory.getBean("userService");
2. ApplicationContext(BeanFactory 子接口,日常开发用)
功能增强容器,项目标准容器,容器启动时立即实例化所有单例 Bean,额外能力:
- 国际化支持
- 资源加载(文件 / 类路径)
- 事件发布监听
- 注解自动扫描 常用实现类:
ClassPathXmlApplicationContext:类路径读取 XMLFileSystemXmlApplicationContext:磁盘路径 XMLAnnotationConfigApplicationContext:纯注解 / JavaConfig(SpringBoot 默认)WebApplicationContext:Web 环境容器
四、三种依赖注入 DI 方式
1. 构造器注入(推荐,Spring 官方推荐)
通过构造方法传入依赖,强制依赖不为空,不可变对象:
@Component
public class UserService {
private final UserDao userDao;
// 构造注入
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
2. Setter 注入
无参构造 + set 方法注入,适合可选依赖:
@Component
public class UserService {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
3. 字段注入(不推荐,仅测试简单使用)
直接在成员变量加 @Autowired,破坏封装,无法做依赖校验:
@Component
public class UserService {
@Autowired
private UserDao userDao;
}
五、Bean 定义三种配置方式
1. XML 配置(早期 Spring)
<bean id="userDao" class="com.dao.UserDaoImpl"/>
<bean id="userService" class="com.service.UserService">
<constructor-arg ref="userDao"/>
</bean>
2. 注解扫描(SSM 主流)
@Component/@Service/@Repository/@Controller:标记 Bean@Autowired:自动按类型注入@Qualifier("beanName"):同类型多个 Bean 指定名称@Value("${xxx}"):注入配置文件属性
@Repository
public class UserDaoImpl implements UserDao {}
@Service
public class UserService {
@Autowired
private UserDao userDao;
}
3. JavaConfig(SpringBoot 默认,完全替代 XML)
@Configuration 标记配置类,@Bean 手动注册 Bean:
@Configuration
public class SpringConfig {
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
@Bean
public UserService userService(UserDao userDao) {
return new UserService(userDao);
}
}
启动容器:
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
六、Bean 五大作用域
- singleton(默认) :整个容器仅一个实例,容器创建时初始化
- prototype:每次
getBean()创建新对象,多实例 - request:一次 HTTP 请求一个 Bean(Web)
- session:一个用户会话一个 Bean(Web)
- globalSession:集群 Session(Web)
七、Bean 完整生命周期(IOC 容器执行流程)
- 容器读取配置,扫描所有 Bean 定义
- 实例化 Bean(调用无参构造)
- 填充属性(DI 依赖注入)
- 执行
@PostConstruct/ InitializingBean 初始化方法 - Bean 就绪,可供程序使用
- 容器关闭时,执行
@PreDestroy/ DisposableBean 销毁方法
八、IOC 核心优势
- 解耦:业务代码不依赖具体实现,只依赖抽象接口
- 便于单元测试:可轻易 Mock 依赖,无需修改业务代码
- 统一管理对象:单例统一管控,减少内存开销
- 简化代码:消除大量
new、对象装配样板代码 - 为 AOP、事务、缓存等高级功能提供底层支撑
九、IOC 底层核心原理简单概括
- 容器通过反射创建 Bean 对象
- 反射调用构造 /set 方法完成依赖注入
- 用 ConcurrentHashMap 缓存单例 Bean(一级缓存)
- 三级缓存解决循环依赖问题(singleton 循环引用)