Spring IoC 容器填充步骤总结
Spring IoC(Inversion of Control)容器填充是 Spring 应用启动过程中的关键环节。以下是对容器填充步骤的详细解析,并结合丰富的源码示例、中文注释和更新后的 UML 流程图来说明每个步骤的作用及其在代码中的实现。
1. 准备上下文(Prepare the Context)
在 Spring 容器刷新前,Spring 会首先准备上下文环境。这包括设置启动时间、激活上下文标志和准备事件集合。
关键源码:
// 准备刷新上下文
protected void prepareRefresh() {
// 切换上下文为激活状态
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 初始化占位符属性源
initPropertySources();
// 验证所有必需属性是否已解析
getEnvironment().validateRequiredProperties();
// 允许收集早期的 ApplicationEvents
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2. 刷新 BeanFactory(Refresh the BeanFactory)
刷新 BeanFactory 是指销毁旧的 Bean 实例并加载新的 Bean 定义,确保上下文中的 BeanFactory 是最新的。
关键源码:
// 获取并刷新 BeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory(); // 刷新 BeanFactory
return getBeanFactory(); // 返回 BeanFactory
}
3. 初始化 BeanFactory(Initialize the BeanFactory)
初始化 BeanFactory 过程中,设置类加载器、表达式解析器等必要的配置,并注册一些默认的环境 Bean。
关键源码:
// 准备 BeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加属性编辑器注册器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 注册默认环境 Bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
}
4. 后处理 BeanFactory(Post-Process the BeanFactory)
在 BeanFactory 标准初始化后,允许进一步自定义 BeanFactory 的设置。
关键源码:
// BeanFactory 后处理
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 子类可覆盖此方法,进行定制化处理
}
5. 调用 BeanFactory 后处理器(Invoke BeanFactory Post-Processors)
Spring 会调用所有注册的 BeanFactoryPostProcessor
,如 ConfigurationClassPostProcessor
,负责解析 @Configuration
类并注册相应的 Bean 定义。
关键源码:
// 调用 BeanFactory 后处理器
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
6. 注册 BeanPostProcessor(Register BeanPostProcessor)
Spring 注册 BeanPostProcessor
,这些处理器会在每个 Bean 实例化前后进行拦截处理。
关键源码:
// 注册 BeanPostProcessor
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
7. 初始化消息源(Initialize MessageSource)
消息源用于国际化支持,Spring 会在容器中查找或注册默认的 MessageSource
实例。
关键源码:
// 初始化消息源
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
} else {
this.messageSource = new ResourceBundleMessageSource();
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
}
}
8. 初始化事件广播器(Initialize Event Multicaster)
事件广播器负责在容器内分发事件。
关键源码:
// 初始化事件广播器
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
9. 刷新应用上下文(Refresh the Application Context)
在特定的子类上下文中执行刷新操作,通常在 Web 应用中用于启动 Web 服务器。
关键源码:
// 刷新上下文
protected void onRefresh() throws BeansException {
// 子类可覆盖此方法,进行特定的刷新操作
}
10. 注册监听器(Register Listeners)
注册事件监听器,并将其绑定到事件广播器上,以便在容器运行期间接收事件。
关键源码:
// 注册监听器
protected void registerListeners() {
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
}
11. 实例化单例(Instantiate Singletons)
实例化所有的非懒加载的单例 Bean,并在上下文中注册。
关键源码:
// 完成 BeanFactory 初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化上下文的转换服务
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 注册嵌入式值解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 初始化 LoadTimeWeaverAware Bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停止使用临时类加载器进行类型匹配
beanFactory.setTempClassLoader(null);
// 缓存所有的 Bean 定义元数据
beanFactory.freezeConfiguration();
// 实例化所有剩余的非懒加载单例 Bean
beanFactory.preInstantiateSingletons();
}
总结
Spring IoC 容器填充是 Spring 应用启动过程中的一个复杂但至关重要的过程。通过丰富的源码示例、详细的中文注释和清晰的流程图,可以深入理解 Spring 容器的工作机制。每个步骤都展示了 Spring 框架的灵活性和扩展性,使得它能够满足各种应用场景的需求。