一、Spring IOC 容器概述
Spring IOC(Inversion of Control,控制反转)是 Spring 框架的核心功能之一,通过 ** 依赖注入(Dependency Injection)** 实现对象的创建和管理。IOC 容器的主要职责包括:
- 对象定义:通过 XML 配置、Java 注解或 Java 代码定义 Bean。
- 对象创建:根据 Bean 定义创建和初始化对象。
- 依赖管理:解析 Bean 之间的依赖关系,并注入依赖。
- 生命周期管理:管理 Bean 的生命周期(初始化、销毁等)。
Spring 提供了多种 IOC 容器实现,其中最核心的是 BeanFactory
和 ApplicationContext
。
二、核心接口与类层次
2.1 核心接口
- BeanFactory:基础 IOC 容器接口,提供 Bean 的获取、查询等基本功能。
public interface BeanFactory { Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; // 其他方法... }
- ApplicationContext:
BeanFactory
的子接口,扩展了企业级功能(如事件发布、国际化支持等)。 - BeanDefinition:描述 Bean 的元数据(类名、作用域、依赖关系等)。
- BeanDefinitionRegistry:注册和管理
BeanDefinition
的接口。
2.2 主要实现类
- XmlBeanFactory(已弃用):基于 XML 配置的基础容器。
- ClassPathXmlApplicationContext:从类路径加载 XML 配置的应用上下文。
- FileSystemXmlApplicationContext:从文件系统加载 XML 配置的应用上下文。
- AnnotationConfigApplicationContext:基于 Java 注解配置的应用上下文。
三、初始化流程详解
3.1 资源定位与加载
- 配置资源定位:根据配置文件路径(如
classpath:applicationContext.xml
)或配置类(如@Configuration
类)定位资源。 - 资源加载:通过
ResourceLoader
将配置资源加载为Resource
对象。
// 示例:使用 ClassPathXmlApplicationContext 加载资源
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
3.2 BeanDefinition 解析与注册
- 解析配置文件:
- XML 配置:通过
BeanDefinitionDocumentReader
解析 XML 文件,生成BeanDefinition
。 - 注解配置:通过
ClassPathBeanDefinitionScanner
扫描带@Component
、@Service
等注解的类,生成BeanDefinition
。
- XML 配置:通过
- 注册 BeanDefinition:将解析后的
BeanDefinition
注册到BeanDefinitionRegistry
(通常是DefaultListableBeanFactory
)。
3.3 BeanFactory 初始化
- 创建底层 BeanFactory:通常是
DefaultListableBeanFactory
。 - 设置 BeanFactory 属性:如类加载器、Bean 表达式解析器等。
- 应用 BeanPostProcessor:注册实现了
BeanPostProcessor
接口的 Bean,用于在 Bean 初始化前后进行自定义处理。
3.4 容器后置处理
- 调用 BeanFactoryPostProcessor:执行实现了
BeanFactoryPostProcessor
接口的 Bean,允许在 Bean 实例化前修改BeanDefinition
。- 典型实现:
PropertySourcesPlaceholderConfigurer
(解析配置文件中的占位符)。
- 典型实现:
3.5 Bean 实例化与依赖注入
- 创建单例 Bean:
- 按依赖顺序创建单例 Bean(默认在容器初始化时创建)。
- 通过反射或 CGLIB 创建 Bean 实例。
- 依赖注入:
- 基于构造函数注入:通过
AutowiredAnnotationBeanPostProcessor
处理@Autowired
、@Inject
注解。 - 基于字段或方法注入:解析
@Autowired
、@Resource
等注解,完成依赖注入。
- 基于构造函数注入:通过
3.6 Bean 生命周期回调
- 初始化前处理:调用
BeanPostProcessor
的postProcessBeforeInitialization
方法。 - 初始化方法调用:
- 实现
InitializingBean
接口的afterPropertiesSet()
方法。 - 自定义初始化方法(通过
@PostConstruct
或 XML 的init-method
属性)。
- 实现
- 初始化后处理:调用
BeanPostProcessor
的postProcessAfterInitialization
方法(如 AOP 代理在此阶段生成)。
3.7 容器初始化完成
- 发布容器事件:发布
ContextRefreshedEvent
通知容器已初始化完成。 - 启动生命周期处理器:调用实现了
Lifecycle
接口的 Bean 的start()
方法。
四、关键源码分析
4.1 AbstractApplicationContext#refresh()
refresh()
方法是容器初始化的核心入口,包含了完整的初始化流程:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新环境
prepareRefresh();
// 获取 BeanFactory(通常是 DefaultListableBeanFactory)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备 BeanFactory
prepareBeanFactory(beanFactory);
try {
// 允许子类对 BeanFactory 进行后置处理
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 初始化消息源(国际化支持)
initMessageSource();
// 初始化事件广播器
initApplicationEventMulticaster();
// 子类可重写此方法进行额外处理
onRefresh();
// 注册监听器
registerListeners();
// 实例化所有剩余的单例 Bean
finishBeanFactoryInitialization(beanFactory);
// 完成刷新,发布事件
finishRefresh();
}
catch (BeansException ex) {
// 异常处理...
}
finally {
// 重置公共缓存
resetCommonCaches();
}
}
}
4.2 Bean 实例化与依赖注入流程
// AbstractAutowireCapableBeanFactory#createBean()
@Override
protected Object createBean(String beanName, BeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 解析 Bean 的类
resolveBeanClass(mbd, beanName);
// 准备方法覆盖(处理 lookup-method 和 replace-method)
prepareMethodOverrides(mbd, beanName);
try {
// 让 BeanPostProcessor 有机会提前创建代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// 实际创建 Bean
return doCreateBean(beanName, mbdToUse, args);
}
// AbstractAutowireCapableBeanFactory#doCreateBean()
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 创建 Bean 实例(通过构造函数或工厂方法)
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
// 处理合并后的 BeanDefinition
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// 处理循环依赖(提前暴露半成品 Bean)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 填充 Bean 属性(依赖注入)
populateBean(beanName, mbd, instanceWrapper);
// 初始化 Bean(调用初始化方法和 BeanPostProcessor)
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 处理循环依赖相关逻辑
if (earlySingletonExposure) {
// ...
}
// 注册 DisposableBean(用于销毁回调)
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
五、初始化流程优化与扩展
5.1 延迟初始化
通过 @Lazy
注解或 XML 的 lazy-init="true"
属性,可延迟 Bean 的初始化到首次使用时:
@Bean
@Lazy
public MyService myService() {
return new MyService();
}
5.2 自定义 BeanFactoryPostProcessor
通过实现 BeanFactoryPostProcessor
,可在 Bean 实例化前修改 BeanDefinition
:
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("myBean");
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}
5.3 自定义 BeanPostProcessor
通过实现 BeanPostProcessor
,可在 Bean 初始化前后进行自定义处理(如 AOP 代理):
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在初始化前处理
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 在初始化后处理(如生成代理)
return bean;
}
}
六、常见问题与解决方案
6.1 循环依赖问题
- 问题描述:Bean A 依赖 Bean B,而 Bean B 又依赖 Bean A,导致初始化死循环。
- 解决方案:
- Spring 通过三级缓存(singletonFactories、earlySingletonObjects、singletonObjects)解决单例 Bean 的 setter 注入循环依赖。
- 构造函数注入的循环依赖无法自动解决,需重构代码或使用
@Lazy
延迟加载。
6.2 初始化顺序问题
- 问题描述:某些 Bean 需要在其他 Bean 初始化完成后才能初始化。
- 解决方案:
- 使用
@DependsOn
注解指定依赖关系。 - 实现
InitializingBean
或@PostConstruct
进行初始化逻辑。
- 使用
6.3 Bean 初始化失败排查
- 查看异常堆栈:定位具体出错的 Bean。
- 启用调试日志:配置
org.springframework
日志级别为 DEBUG,查看详细初始化过程。 - 使用 BeanPostProcessor:在关键 Bean 初始化前后添加日志记录。
七、总结
Spring IOC 容器的初始化是一个复杂的过程,涉及资源加载、BeanDefinition 解析、依赖注入和生命周期管理等多个阶段。理解其核心流程有助于:
- 性能优化:合理配置延迟加载、避免循环依赖。
- 功能扩展:通过自定义
BeanFactoryPostProcessor
和BeanPostProcessor
扩展容器功能。 - 问题排查:快速定位 Bean 初始化失败、依赖解析错误等问题。
掌握 IOC 容器的初始化流程是深入理解 Spring 框架的关键一步,也是开发高效、稳定的 Spring 应用的基础。