序言
Spring 是 Java 生态中最流行的轻量级框架之一,其核心是 IoC(控制反转)容器 和 AOP(面向切面编程)。理解 Spring 的源码不仅有助于我们更好地掌握其内部机制,还能提升我们在实际开发中对配置、性能优化以及问题排查的能力。
本文将以 Spring Framework 6.x 为基础,重点解析 Spring 容器的启动流程,深入探讨 ApplicationContext、BeanFactory、BeanDefinition 等核心组件的实现原理。
1. Spring 启动流程概述
Spring 容器的启动过程主要分为以下几个阶段:
- 加载配置
- 创建 BeanFactory
- 注册 BeanDefinition
- 刷新上下文(refresh)
- 实例化单例 Bean
以最常见的 ClassPathXmlApplicationContext 或 AnnotationConfigApplicationContext 为例,入口代码如下:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml")
或者使用注解方式:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
无论是 XML 配置还是注解驱动,最终都会调用 AbstractApplicationContext.refresh() 方法完成整个容器的初始化。
我们使用 Spring 的大多时候都是直接创建容器然后使用,没有思考过或者研究过 Spring 为什么可以这样。所以接下来我们就来看看这两行创建的对象过程中 Spring 究竟做了什么。
2. 核心组件与流程详解
ApplicationContext 、 BeanFactory 和 ListableBeanFactory
熟悉 Spring 框架的对这两个容器都是再熟悉不过了,就不多介绍这两个类了,这里要介绍的是 ListableBeanFactory 这个容器。下面是 Spring 源码对这个类的介绍
/**
* 对 {@link BeanFactory} 接口的扩展,适用于能够列举所有 bean 实例的工厂实现。
* 与按需逐个通过名称查找不同,该接口支持批量获取 bean 名称和实例。
* 常见于预加载所有 bean 定义的容器(如基于 XML 或注解配置的工厂)。
*
* <p>如果此工厂是 {@link HierarchicalBeanFactory},则返回值不会考虑父工厂中的 bean,
* 仅限当前工厂中定义的 bean。如需包含祖先工厂中的 bean,请使用工具类 {@link BeanFactoryUtils}。
*
* <p>本接口的方法主要作用于通过 bean 定义注册的 bean,忽略通过其他方式手动注册的 singleton(如
* 通过 {@link org.springframework.beans.factory.config.ConfigurableBeanFactory#registerSingleton}
* 注册的 bean),但某些方法如 {@code getBeanNamesForType} 和 {@code getBeansOfType}
* 也会检查这些手动注册的单例。
*
* <p><b>注意</b>:除了 {@code getBeanDefinitionCount} 和 {@code containsBeanDefinition} 方法外,
* 其他方法不是为频繁调用设计的,性能可能较差。
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 16 April 2001
* @see HierarchicalBeanFactory
* @see BeanFactoryUtils
*/
public interface ListableBeanFactory extends BeanFactory {
// 方法省略
}
三者的关系如下:
这个接口支持批量获取 bean 名称和实例,当需要遍历所有的 bean 来执行某些操作,比如初始化、验证等就会非常有用。
继续来看创建一个 ClassPathXmlApplicationContext 对象,Spring 究竟做了哪些事情。点开源码发现最后会调用下面的这段代码
/**
* 使用给定的父上下文创建一个新的 ClassPathXmlApplicationContext,
* 并从指定的 XML 文件中加载 bean 定义。
*
* @param configLocations 资源位置数组,用于定位配置文件
* @param refresh 是否自动刷新上下文,加载所有 bean 定义并创建所有单例 bean;
* 如果为 false,则可以在进一步配置上下文后手动调用 refresh() 方法
* @param parent 父应用上下文,可选参数,用于设置上下文的继承关系
* @throws BeansException 如果上下文创建或初始化过程中发生异常
* @see #refresh()
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
接下来介绍一下这三个方法具体在做什么操作
super(parent)
我们知道 Spring 有一个强大的机制可以支持容器之间的继承,这种机制被称为"父子容器"(Parent-Child Container)关系。其作用是实现多个上下文之间共享一些通用配置。比如Bean对象的访问等。子容器可以访问父容器里的Bean,而父容器不能访问子容器的Bean。
一直追溯这个方法,会调用到如下逻辑:
/**
* Create a new AbstractApplicationContext with the given parent context.
* @param parent the parent context
*/
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();
setParent(parent);
}
this() 方法的作用是创建一个 ResourcePatternResolver对象并赋值给自身的 private final ResourcePatternResolver resourcePatternResolver;属性,这个类主要用于解析资源路径,支持通配符、递归搜索的资源查找
setParent()方法的作用设置当前应用的父级上下文
@Override
public void setParent(@Nullable ApplicationContext parent) {
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment configurableEnvironment) {
getEnvironment().merge(configurableEnvironment);
}
}
}
这里会调用 merge() 方法来合并
public void merge(ConfigurableEnvironment parent) {
Iterator var2 = parent.getPropertySources().iterator();
// 合并 PropertySources(属性源)
while(var2.hasNext()) {
PropertySource<?> ps = (PropertySource)var2.next();
if (!this.propertySources.contains(ps.getName())) {
this.propertySources.addLast(ps);
}
}
// 合并 ActiveProfiles(激活的 Profile)
String[] parentActiveProfiles = parent.getActiveProfiles();
if (!ObjectUtils.isEmpty(parentActiveProfiles)) {
synchronized(this.activeProfiles) {
Collections.addAll(this.activeProfiles, parentActiveProfiles);
}
}
// 合并 DefaultProfiles(默认的 Profile)
String[] parentDefaultProfiles = parent.getDefaultProfiles();
if (!ObjectUtils.isEmpty(parentDefaultProfiles)) {
synchronized(this.defaultProfiles) {
this.defaultProfiles.remove("default");
Collections.addAll(this.defaultProfiles, parentDefaultProfiles);
}
}
}
这段代码运行完毕后,子容器就会拥有父容器的信息。
setConfigLocations(configLocations)
这个方法的主要作用就是将传入的 configLocations 配置位置保存下来,这些位置会在后续调用 refresh() 方法时被用来加载 XML 配置文件中的 Bean 定义。
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
这里会对这个资源路径进行解析,大家可以打断点调试一下,主要是解析通配符,比如 ${ }这些特殊字符,解析完成后会把路径存放到 configLocations 的字符数组中。
3. refresh 方法
接下来就是最重要的 refresh 方法,几乎所有的工作量都在这个方法里面完成的。
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock(); // 加锁防止并发刷新
try {
this.startupShutdownThread = Thread.currentThread();
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
prepareRefresh(); // 准备刷新:设置状态、校验必需属性
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 获取 BeanFactory(解析 XML 或 注解)
prepareBeanFactory(beanFactory); // 配置 BeanFactory 的基础功能(类加载器、表达式解析器等)
try {
postProcessBeanFactory(beanFactory); // 子类扩展点:可以在此修改 BeanFactory
invokeBeanFactoryPostProcessors(beanFactory); // 执行所有 BeanFactoryPostProcessor(如 PropertyPlaceholderConfigurer)
registerBeanPostProcessors(beanFactory); // 注册 BeanPostProcessor(如 AutowiredAnnotationBeanPostProcessor)
initMessageSource(); // 初始化国际化消息源
initApplicationEventMulticaster(); // 初始化应用事件广播器
onRefresh(); // 子类扩展点:可自定义刷新逻辑(如 WebApplicationContext 创建 Web 容器)
registerListeners(); // 注册监听器(包括 ApplicationListener bean)
finishBeanFactoryInitialization(beanFactory); // 实例化所有非懒加载单例 Bean
finishRefresh(); // 完成刷新:发布上下文刷新完成事件、生命周期处理器等
} catch (异常) { ... }
finally {
contextRefresh.end();
}
}
finally {
this.startupShutdownThread = null;
this.startupShutdownLock.unlock(); // 解锁
}
}
接下来一一阅读这些方法的源码
prepareRefresh()
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
1. 设置启动时间 & 激活状态
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
startupDate:记录容器的启动时间。closed.set(false):表示上下文未关闭。active.set(true):标记上下文处于激活状态(正在运行中)。
📌 这些状态信息在容器生命周期管理和日志输出中很有用。
2. 打印日志
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
- 如果启用了调试日志,则打印当前正在刷新的上下文信息。
getDisplayName()返回的是上下文的名称或类名。
3. 初始化属性源(Property Sources)
initPropertySources();
- 这是一个钩子方法(hook method) ,供子类重写以添加自定义的属性源。
- 默认实现为空。
- 示例:子类可以在这里添加数据库配置、系统参数等自定义属性源。
📌 子类如 GenericWebApplicationContext 会覆盖此方法来添加 Web 环境相关的属性。
4. 验证必须的属性是否都已配置
getEnvironment().validateRequiredProperties();
- 获取当前环境对象(
ConfigurableEnvironment)并调用validateRequiredProperties()。 - 该方法会检查所有被标记为“required”的属性是否都存在于环境中。
- 如果有缺失,抛出异常(通常是
MissingRequiredPropertiesException)。
✅ 这个机制可以用来保证某些关键属性(如数据库连接URL、用户名密码)在应用启动前已经正确配置。
5. 保存早期监听器(ApplicationListeners)
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
- 保存或恢复事件监听器集合(即
ApplicationListener)。 - 在上下文刷新前,有些监听器可能已经被注册(比如通过编程方式添加),这个步骤是为了防止它们在刷新过程中丢失。
📌 earlyApplicationListeners 是一个临时存储结构,在 refresh() 前后用于保留原始监听器状态。
6. 准备早期事件队列
this.earlyApplicationEvents = new LinkedHashSet<>();
- 创建一个新的集合用于缓存“早期事件”。
- 在
refresh()的早期阶段,事件广播器(ApplicationEventMulticaster)还未初始化完成,无法发布事件。 - 因此,这些事件会被暂存在
earlyApplicationEvents中,待事件广播器初始化完成后统一发布。
📌 典型使用场景:ContextRefreshedEvent 就是在这里延迟发布的。
obtainFreshBeanFactory
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
1.刷新上下文
方法的代码如下:
这段代码位于AbstractRefreshableApplicationContext抽象类,上文中的 ClassPathXmlApplicationContext间接继承了这个抽象类。
@Override
protected final void refreshBeanFactory() throws BeansException {
// 销毁已有 Bean 和关闭旧的 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try
// 创建新的 DefaultListableBeanFactory 实例
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 自定义 BeanFactory 属性
// 这个方法点进去后就是设置是否允许循环依赖和Bean覆盖
customizeBeanFactory(beanFactory);
// 加载 Bean 定义
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
对于loadBeanDefinitions(beanFactory)方法,大家点进源码后会发现下面这段代码
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
getConfigLocations()方法就会获取上文中的 configLocations 配置文件,然后进行解析这个xml文件加载Bean。方法嵌套的比较多,这里就不一一展示了,大家可以点击源码自行阅读具体实现。
上下文创建完毕后就调用 getBeanFactory方法返回。
prepareBeanFactory
prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) 方法是 Spring 容器初始化过程中的一部分,主要用于配置 BeanFactory 的基础功能和注册一些必要的依赖。这个方法在 AbstractApplicationContext 类中定义。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 BeanFactory 使用上下文的类加载器等。
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 配置 BeanFactory 以支持上下文回调。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// 注册一些默认的可解析依赖。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 注册一个用于检测内部 Bean 是否为 ApplicationListeners 的后处理器。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 检测是否存在 LoadTimeWeaver 并准备织入(如果存在)。
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// 设置一个临时的 ClassLoader 用于类型匹配。
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认的环境 Bean。
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
详细步骤说明
1. 设置类加载器和其他基础组件
setBeanClassLoader(): 设置BeanFactory使用的类加载器,通常是从当前上下文中获取的。setBeanExpressionResolver(): 设置一个标准的 Bean 表达式解析器,支持在 Bean 定义中使用 SpEL (Spring Expression Language)。addPropertyEditorRegistrar(): 添加一个属性编辑器注册器,主要用于处理资源类型的属性值(如路径、URL 等),使其能够正确地转换为相应的对象类型。
2. 配置上下文感知接口
addBeanPostProcessor(new ApplicationContextAwareProcessor(this)): 添加一个ApplicationContextAwareProcessor,它会自动将上下文信息注入到实现了特定接口(如ApplicationContextAware,ResourceLoaderAware等)的 Bean 中。- 忽略某些依赖接口: 对于某些接口(如
EnvironmentAware),通过ignoreDependencyInterface()来告诉BeanFactory忽略这些接口作为依赖注入的目标。这样做的目的是避免不必要的依赖注入循环。
3. 注册可解析依赖
registerResolvableDependency(): 注册一些常见的可解析依赖类型(如BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext),使得它们可以直接被自动装配(autowired)。
4. 添加 Bean 后处理器
addBeanPostProcessor(new ApplicationListenerDetector(this)): 添加一个ApplicationListenerDetector,它会在 Bean 创建过程中检测是否实现了ApplicationListener接口,并将其注册为事件监听器。
5. Load-Time Weaving 支持
- 如果应用上下文中存在名为
loadTimeWeaver的 Bean,则会添加一个LoadTimeWeaverAwareProcessor,并设置一个临时的ClassLoader用于类型匹配。这主要用于 AOP 功能中的运行时织入。
6. 注册默认的环境 Bean
-
如果
BeanFactory中还没有包含特定名称的 Bean,则会注册一些默认的环境相关的单例 Bean,包括:environment: 当前的Environment实例。systemProperties: 系统属性。systemEnvironment: 系统环境变量。applicationStartup: 应用启动信息。
postProcessBeanFactory
这个方法允许子类或者外部的扩展点对 BeanFactory 进行进一步定制化处理。这是一个 空实现(no-op) 的方法,在 AbstractApplicationContext 中默认什么都不做。
有一些类重写了这个方法,比如在 AbstractRefreshableWebApplicationContext 上下文中,会重写这个方法来添加 Web 相关的支持:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加 ServletContextAwareProcessor BeanPostProcessor 到 BeanFactory
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
// 忽略 ServletContextAware 和 ServletConfigAware 接口作为自动装配的候选者
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
// 注册 Web 应用的作用域(如 request, session)到 BeanFactory
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
// 注册环境相关的 Bean(如 servletContext, servletConfig)到 BeanFactory
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
这种定制化让 Spring 容器更好地适应 Web 应用的需求,并提供了更加灵活和强大的功能支持
invokeBeanFactoryPostProcessors
这个方法就很好理解了,在上一个方法 postProcessBeanFactory 中添加了不同环境的BeanFactory实现,这一步就是调用这些方法,代码就不展示了。
registerBeanPostProcessors
这个方法的主要职责是查找并注册所有 BeanPostProcessor 实现类到给定的 BeanFactory 中。这些处理器将在 Bean 实例化和初始化过程中被调用,允许开发者在 Bean 的生命周期不同阶段执行自定义逻辑。点进源码后会发现下面这段代码:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(
new BeanPostProcessorChecker(beanFactory, postProcessorNames, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
1 取所有 BeanPostProcessor Bean 名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
-
这一步从
BeanFactory中找出所有实现了BeanPostProcessor接口的 Bean。 -
参数说明:
true: 表示只查找非单例但可配置的 Bean。false: 不考虑对象类型的匹配问题。
2️ 添加 BeanPostProcessorChecker
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, postProcessorNames, beanProcessorTargetCount));
- 这是一个用于调试的日志检查器。
- 如果某个 Bean 在
BeanPostProcessor实例化之前就被创建了,会记录一个提示信息,因为这可能导致某些后处理器无法处理这个 Bean。
3️ 分类处理不同的 BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
遍历所有找到的 BeanPostProcessor Bean 名称,并根据它们是否实现了以下接口进行分类:
| 分类 | 接口 | 处理方式 |
|---|---|---|
priorityOrderedPostProcessors | PriorityOrdered | 第一优先级加载 |
orderedPostProcessorNames | Ordered | 第二优先级加载 |
nonOrderedPostProcessorNames | 无 | 最后加载 |
internalPostProcessors | 特殊类型如 MergedBeanDefinitionPostProcessor | 后续再次注册 |
4️ 注册 PriorityOrdered 类型的处理器
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
- 先对这些处理器排序。
- 然后依次注册到
BeanFactory中。
5️ 注册 Ordered 类型的处理器
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
- 实例化每个
Ordered类型的BeanPostProcessor - 如果是内部处理器,加入
internalPostProcessors
6️ 注册没有实现排序接口的普通处理器
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
- 这些处理器执行顺序不保证,但仍然会被注册。
7️ 重新注册内部处理器(如 AutowiredAnnotationBeanPostProcessor)
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
- 内部处理器通常需要在整个链表的末尾执行,以确保能够处理所有已经代理或合并定义的 Bean。
8️ 确保 ApplicationListenerDetector 放到最后
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
- 这个特殊的处理器用于检测哪些 Bean 是
ApplicationListener。 - 放到最后是为了确保能正确识别代理后的 Bean(例如 AOP 代理)。
initMessageSource
它在 Spring 容器初始化过程中负责 初始化或注册 MessageSource,这是 Spring 支持国际化(i18n)的核心组件。代码如下:
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource hms &&
hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
该方法的主要职责:
- 查找是否定义了自定义的
messageSourceBean - 如果没有,则创建一个默认的
DelegatingMessageSource实例 - 设置父上下文的消息源(如果有),形成消息继承链
- 将
MessageSource注册为单例 Bean 并赋值给上下文
对于 initApplicationEventMulticaster方法代码的实现逻辑和这个差不多,就不单独介绍了
总结
每个方法的作用如下:
| 阶段 | 方法名 | 所属类 | 主要作用 | 核心逻辑说明 |
|---|---|---|---|---|
| 1. 准备刷新 | prepareRefresh() | AbstractApplicationContext | 初始化上下文环境,准备刷新容器 | 设置启动时间、初始化属性源、校验必需的配置项 |
| 2. 获取 BeanFactory | obtainFreshBeanFactory() | AbstractApplicationContext | 创建或获取一个 ConfigurableListableBeanFactory 实例 | 刷新 BeanFactory,加载并解析 Bean 定义(如 XML 或注解) |
| 3. 配置 BeanFactory | prepareBeanFactory(ConfigurableListableBeanFactory) | AbstractApplicationContext | 为 BeanFactory 添加基础支持功能 | 设置 ClassLoader、添加 PropertyEditor、注册默认的 Environment Bean 等 |
| 4. 子类扩展点 | postProcessBeanFactory(ConfigurableListableBeanFactory) | AbstractApplicationContext(子类实现) | 允许子类对 BeanFactory 做进一步定制 | 如 Web 应用上下文可在此添加 Web 相关组件 |
| 5. 调用 BeanFactory 后处理器 | invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory) | PostProcessorRegistrationDelegate | 调用所有 BeanFactoryPostProcessor | 修改或扩展 BeanDefinition(如 @ComponentScan 的处理) |
| 6. 注册 Bean 后处理器 | registerBeanPostProcessors(ConfigurableListableBeanFactory) | PostProcessorRegistrationDelegate | 注册 BeanPostProcessor 实现类 | 如 AOP 功能依赖的 InstantiationAwareBeanPostProcessor |
| 7. 初始化消息源 | initMessageSource() | AbstractApplicationContext | 初始化国际化消息支持 | 查找自定义 messageSource,否则创建默认 DelegatingMessageSource |
| 8. 初始化事件广播器 | initApplicationEventMulticaster() | AbstractApplicationContext | 初始化事件发布机制 | 使用默认或自定义的 ApplicationEventMulticaster |
| 9. 自定义刷新逻辑 | onRefresh() | AbstractApplicationContext(子类重写) | 子类提供特定于上下文的刷新行为 | 如 Web 容器中启动嵌入式服务器 |
| 10. 注册监听器 | registerListeners() | AbstractApplicationContext | 注册所有 ApplicationListener Bean | 保证事件能被监听和响应 |
| 11. 初始化单例 Bean | finishBeanFactoryInitialization(ConfigurableListableBeanFactory) | AbstractApplicationContext | 实例化所有非懒加载的单例 Bean | 包括依赖注入、AOP 代理生成等 |
感谢阅读!