Spring IoC 详解

IoC 简介

IoC 是什么

IoC控制反转 (Inversion of Control),也被称为依赖倒置原则,是设计模式六大原则之一。其核心思想是程序应依赖抽象接口,而非具体实现,从而降低代码间的耦合度。

IoC 的实现方式包括两种:

  • 依赖注入(DI):不通过类内部直接创建依赖对象,而是将外部创建好的依赖对象通过构造函数或参数传递给类使用。
  • 依赖查找:受控对象通过容器 API 查找所需资源和协作对象。

理解 IoC 的关键在于两点:

  1. 谁控制谁,控制什么:传统编程中,对象由程序主动创建;而 IoC 中,对象由容器控制创建,容器负责管理外部资源获取。
  2. 为何反转,哪些方面反转:传统方式是程序主动获取依赖对象(正转),而 IoC 中容器负责创建并注入依赖对象(反转),依赖对象的获取方式发生了反转。

IoC 的作用

IoC 是一种编程思想,而非具体技术,作为面向对象编程的重要法则,它指导设计松耦合的程序。传统方式中,类内部主动创建依赖对象导致高耦合,难以测试;IoC 将对象的创建和查找交由容器管理,使对象间松散耦合,便于测试和复用,提升程序体系结构的灵活性。IoC 体现了"主从换位"思想,应用程序从主动获取资源变为被动接受容器注入,符合"好莱坞法则":别找我们,我们找你。

IoC 与 DI

IoC 和依赖注入(DI)是从不同角度描述同一概念。IoC 强调控制权的反转,而 DI 更明确地指出依赖对象由容器注入。2004 年,Martin Fowler 提出"依赖注入"这一术语,以更清晰地表达这一过程。

IoC 容器

IoC 容器是具备依赖注入功能的容器,负责实例化、定位、配置应用程序中的对象并管理其依赖关系。在 Spring 中,BeanFactory 是 IoC 容器的基础实现,通过配置文件(如 XML、注解或 Java 代码)定义对象的元数据,容器据此完成对象的组装。

Bean

由 IoC 容器管理的对象称为 Bean。Bean 是容器初始化、装配和管理的对象,其定义通过配置元数据(如 BeanDefinition)指定,描述如何实例化和组装。

Spring IoC

Spring IoC 容器通过构造函数参数、工厂方法参数或属性设置定义 Bean 的依赖关系,创建时由容器注入这些依赖。这一过程是对象主动控制依赖的反转,因此称为控制反转。核心包 org.springframework.beansorg.springframework.context 提供了 IoC 容器的基础支持。

IoC 容器

Spring 提供两种 IoC 容器:

  • BeanFactory:基础 IoC 容器,提供配置框架和基本功能。
  • ApplicationContextBeanFactory 的子接口,扩展了国际化、资源访问、事件机制等功能,适用于大多数场景。

实际开发中,推荐使用 ApplicationContext,因其功能更丰富。ApplicationContext 接口负责实例化、配置和组装 Bean,通过配置元数据(XML、注解或 Java 代码)获取指令。

常见实现包括:

  • ClassPathXmlApplicationContext:从类路径加载配置。
  • FileSystemXmlApplicationContext:从文件系统加载配置。

使用 IoC 容器的步骤包括:

  1. 配置元数据:定义容器如何初始化和管理 Bean。
  2. 实例化容器 :容器解析元数据,生成 BeanDefinition 并完成 Bean 的实例化与组装。
  3. 使用容器:客户端通过容器获取所需 Bean。

配置元数据

配置元数据描述 Bean 的属性和依赖,可通过以下方式实现:

  • XML 配置 :传统方式,使用 <bean> 元素定义。
  • 注解配置:Spring 2.5 引入,通过注解简化配置。
  • Java 配置:Spring 3.0 引入,使用 Java 代码定义。

实例化容器

通过指定资源路径(如 XML 文件)实例化 ApplicationContext,例如:

java 复制代码
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

支持通过多个 XML 文件分层定义 Bean,使用 <import/> 元素组合:

xml 复制代码
<beans>
    <import resource="services.xml"/>
    <bean id="bean1" class="..."/>
</beans>

使用容器

通过 getBean 方法获取 Bean 实例:

java 复制代码
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml");
PetStoreService service = context.getBean("petStore", PetStoreService.class);

IoC 配置元数据

XML 配置

XML 配置是 Spring 的传统方式,基本结构如下:

xml 复制代码
<beans>
    <bean id="bean1" class="..."/>
    <alias alias="bean3" name="bean2"/>
    <import resource="resource.xml"/>
</beans>
  • <bean> 定义 Bean,id 为唯一标识,class 指定类名。
  • <alias> 设置别名。
  • <import> 导入其他配置文件。

实例化方式:

java 复制代码
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"services.xml", "daos.xml"});

注解配置

Spring 2.5 引入注解配置,需在 XML 中启用:

xml 复制代码
<context:annotation-config/>

常用注解包括:

  • @Required:修饰 setter 方法,确保属性在 XML 中配置。
  • @Autowired:修饰属性、setter 或构造函数,按类型自动注入。
  • @Qualifier :与 @Autowired 配合,按名称指定 Bean。
  • @Resource:按名称注入,支持 JSP 250 标准。
  • @PostConstruct@PreDestroy:定义生命周期方法。
  • @Inject :Spring 3.0 支持的 JSR 330 注解,功能类似 @Autowired

Java 配置

Spring 3.0 引入 Java 配置,使用 @Configuration@Bean 注解:

java 复制代码
@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}
  • @Configuration 标记配置类。
  • @Bean 定义 Bean,等价于 XML 中的 <bean>

实例化:

java 复制代码
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

依赖解决过程

容器解析 Bean 依赖的步骤:

  1. 使用配置元数据创建和初始化 ApplicationContext
  2. 为每个 Bean 提供依赖(属性或构造函数参数)。
  3. 将值或引用转换为实际类型。

Spring 在容器加载时验证配置,延迟设置属性以避免循环依赖问题。单例 Bean 默认预实例化,可通过配置改为延迟初始化。

相关推荐
摇滚侠14 分钟前
DBeaver 导入数据库 导入 SQL 文件 MySQL 备份恢复
java·数据库·mysql
keep one's resolveY38 分钟前
SpringBoot实现重试机制的四种方案
java·spring boot·后端
天空属于哈夫克31 小时前
企业微信API常见的错误和解决方案
java·数据库·企业微信
摇滚侠2 小时前
VMvare 虚拟机 Oracle19c 安装步骤,远程连接 Oracle19c,百度网盘安装包
java·oracle
梁萌2 小时前
idea报错找不到XX包的解决方法
java·intellij-idea·启动报错·缺少包
Agent产品评测局2 小时前
生产排期与MES/ERP系统打通,实操方法详解 —— 2026企业级智能体自动化选型与实战指南
java·运维·人工智能·ai·chatgpt·自动化
阿丰资源2 小时前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
呱牛do it3 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 8)
java
消失的旧时光-19434 小时前
Spring Boot 工程化进阶:统一返回 + 全局异常 + AOP 通用工具包
java·spring boot·后端·aop·自定义注解
NE_STOP4 小时前
Redis--发布订阅命令和Redis事务
java