Spring IoC(控制反转)
Spring IoC(控制反转)是Spring框架的核心功能之一,以下是其核心知识点总结:
一、IoC基础概念
-
控制反转(IoC)
- 核心思想:将对象的创建和依赖管理交给容器,而非手动编码。
- 优势:降低代码耦合度,提高灵活性和可维护性。
-
依赖注入(DI)
- IoC的具体实现方式,通过容器向对象注入依赖。
二、核心接口与容器
-
BeanFactory
- IoC容器的基础接口,提供基本的Bean管理功能(如
getBean()
)。 - 延迟加载:Bean在第一次使用时创建。
- IoC容器的基础接口,提供基本的Bean管理功能(如
-
ApplicationContext
- BeanFactory的高级实现,扩展了功能:
- 支持国际化(
MessageSource
)、事件监听(ApplicationEventPublisher
)、资源加载(ResourcePatternResolver
)等。
- 支持国际化(
- 常见实现类:
ClassPathXmlApplicationContext
(从类路径加载XML配置)。AnnotationConfigApplicationContext
(基于注解配置)。
- BeanFactory的高级实现,扩展了功能:
三、Bean的定义与管理
-
BeanDefinition
- 描述Bean的元数据(类名、作用域、依赖等)。
- 来源:XML配置、注解(如
@Component
)、Java配置类(@Bean
)。
-
Bean的作用域
singleton
(默认,单例)。prototype
(原型,每次获取新实例)。request
/session
(Web环境中请求/会话级)。
-
依赖注入方式
- 构造函数注入:通过构造方法注入依赖(推荐,确保不可变性)。
- Setter方法注入:通过Setter方法注入。
- 字段注入:使用
@Autowired
直接注入字段(不推荐,不利于测试)。
四、Bean的生命周期
-
初始化流程
- 实例化Bean → 填充属性 → 调用
@PostConstruct
注解方法 → 执行InitializingBean
接口的afterPropertiesSet()
→ 自定义初始化方法(XML中init-method
或@Bean(initMethod=)
)。
- 实例化Bean → 填充属性 → 调用
-
销毁流程
- 调用
@PreDestroy
注解方法 → 执行DisposableBean
接口的destroy()
→ 自定义销毁方法(XML中destroy-method
或@Bean(destroyMethod=)
)。
- 调用
五、高级特性
-
自动装配(Autowiring)
@Autowired
:按类型自动装配。@Qualifier
:指定名称装配。@Resource
:JSR-250标准,按名称或类型装配。
-
AOP(面向切面编程)
- 与IoC结合,通过代理模式为Bean添加横切逻辑(如日志、事务)。
-
条件化Bean
@Conditional
:根据条件动态注册Bean(如环境、类是否存在)。
六、配置方式
-
XML配置
- 使用
<bean>
标签定义Bean和依赖关系。
- 使用
-
注解配置
@Component
系列(@Service
、@Repository
等):标记Bean。@Configuration
+@Bean
:替代XML定义Bean。
-
Java配置类
- 通过
@Configuration
类中的@Bean
方法显式定义Bean。
- 通过
七、最佳实践
- 优先使用构造函数注入,确保依赖不可变。
- 避免过度依赖注解,适当结合XML或Java配置提高可读性。
- 理解循环依赖问题及解决方案(如延迟注入
@Lazy
)。 - 合理使用作用域,避免内存泄漏(如
prototype
Bean未被容器管理)。
通过掌握以上知识点,结合源码调试和项目实践,可深入理解Spring IoC的设计思想与应用场景。 Spring 中 IoC 容器主要通过以下方面实现:
核心接口及类
- BeanFactory :IoC 容器的基本实现,是 Spring 内部使用的接口 ,定义了基本的 IoC 容器规范,如包含
getBean()
等基本方法来获取 Bean 。它就像一个 “发动机”,负责实例化 Bean ,建立 Bean 之间的依赖关系,以及控制 Bean 的生命周期 。例如,通过它可以从容器中获取一个已定义好的用户服务 Bean 实例。 - ApplicationContext :BeanFactory 的子接口 ,是更高级的 IoC 容器实现,面向 Spring 的使用者 。它继承了多个接口,具备更多功能:
- 继承
EnvironmentCapable
可访问配置环境;继承ListableBeanFactory
能列出容器中所有 Bean 定义等信息 。 - 继承
ResourcePatternResolver
可加载资源文件;继承MessageSource
能实现国际化;继承ApplicationEventPublisher
可注册监听器实现事件监听机制 。比如在一个多语言的项目中,利用其国际化功能根据用户地区显示对应语言的提示信息 。常见的实现类有:- ClassPathXmlApplicationContext :从类路径中加载 XML 格式的配置文件创建 IoC 容器对象 。
- FileSystemXmlApplicationContext :通过文件系统路径读取 XML 格式的配置文件创建 IoC 容器对象 。
- AnnotationConfigApplicationContext :用于加载基于注解(如
@Configuration
、@Bean
等)的配置来创建 IoC 容器 。
- 继承
Bean 定义与管理
- BeanDefinition :用于描述 Bean 的定义 ,Spring 容器启动时,会将 XML 配置、Java 配置类或注解里的 Bean 定义解析成
BeanDefinition
。它记录了 Bean 的类名、作用域(如单例singleton
、原型prototype
等 )、是否懒加载等元数据信息 。比如在 XML 配置文件中定义<bean id="userService" class="com.example.UserService" scope="singleton"/>
,就会被解析成相应的BeanDefinition
。 - BeanDefinitionRegistry :提供了向 IoC 容器注册
BeanDefinition
对象的方法 ,Spring 容器通过它将解析后的BeanDefinition
注册到容器中进行管理 。
依赖注入实现方式
- 构造函数注入 :通过类的构造函数传入依赖对象 。例如:
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
在配置文件或使用注解配置时,Spring 会根据构造函数参数找到对应的 BeanDefinition
,实例化依赖对象并注入 。
- Setter 方法注入 :利用类的 Setter 方法设置依赖对象 。如下示例:
public class UserService {
private UserRepository userRepository;
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Spring 会调用对应的 Setter 方法来完成依赖注入 。
- 字段注入 :使用注解(如
@Autowired
)直接在类的字段上注入依赖对象 ,例如:
public class UserService {
@Autowired
private UserRepository userRepository;
}
不过这种方式不利于测试和实现依赖不可变,一般不推荐 。
容器初始化与刷新
- 初始化过程 :以
ApplicationContext
为例,创建容器实例时(如new ClassPathXmlApplicationContext("applicationContext.xml")
) ,会经历一系列步骤 。首先定位配置文件资源 ,然后解析配置文件内容,将其中的 Bean 定义加载并注册到容器中 。 - refresh() 方法 :容器创建好后会调用
refresh()
方法 ,该方法定义了整个 Spring 上下文加载的流程 ,包括调用工厂后处理器处理各类 Bean 标签 、扫描 Bean 文件并解析成一个个BeanDefinition
;注册 Bean 后置处理器;初始化事件广播器;注册事件监听器;实例化所有已注册但未被实例化的非懒加载 Bean ;以及完成一些初始化生命周期处理器等操作 ,为 IOC 容器以及 Bean 的生命周期管理提供条件 。