目录
ApplicationEventPublisherAware
(一)添加 ApplicationContextAwareProcessor
(二)添加 ApplicationListenerDetector
干货分享,感谢您的阅读!
在很早之前我们单独写过一篇文章《分析SpringBoot启动配置原理》,具体可见:
一、IOC容器的刷新环节快速回顾
我们将AbstractApplicationContext的refresh方法源码提取并进行重点代码标注说明如下:
public abstract class AbstractApplicationContext implements ApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备上下文环境,包括初始化工厂、后置处理器等
prepareRefresh();
// 创建并初始化 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器、资源加载器等
prepareBeanFactory(beanFactory);
try {
// 允许子类对 BeanFactory 进行进一步的自定义处理
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessors 进行后置处理
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessors,用于对 Bean 实例进行后置处理
registerBeanPostProcessors(beanFactory);
// 初始化消息源
initMessageSource();
// 初始化事件广播器
initApplicationEventMulticaster();
// 初始化其他特殊 Bean
onRefresh();
// 注册关闭钩子
registerListeners();
// 初始化所有剩余的单例 Bean
finishBeanFactoryInitialization(beanFactory);
// 完成上下文刷新
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已创建的 Bean,关闭容器
destroyBeans();
// 重置容器刷新标志,允许再次刷新
cancelRefresh(ex);
// 把异常重新抛出,允许调用者处理
throw ex;
} finally {
// 重置已注册的 JVM 关闭钩子
resetCommonCaches();
}
}
}
}
以上内容请多次翻看并理解(如果忘记了最好在次读一下之前的原文博客进行基本的回顾),我们本次讲聚焦其中的prepareBeanFactory专项展开分析。
二、prepareBeanFactory源码展示分析
prepareBeanFactory
方法是 Spring 容器启动过程中的一个重要环节。它对 BeanFactory
进行一系列的配置和初始化工作,包括设置类加载器、表达式解析器、属性编辑器、注册特定的依赖、添加后置处理器等。通过这些配置,BeanFactory
可以更好地管理和创建 Bean,提供更强大的依赖注入和事件处理能力。
我们针对其主要的源码展示说明如下:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 BeanFactory 的类加载器为当前上下文的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置 BeanFactory 的表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 设置 BeanFactory 的属性编辑器注册
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加 BeanPostProcessor(ApplicationContextAwareProcessor),用于处理特定的回调接口
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.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 注册早期的 PostProcessor 检查 BeanFactory 以便尽早进行特殊处理
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 检查 LoadTimeWeaver 并设置到 BeanFactory 中(用于 AspectJ 织入)
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
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());
}
}
通过 prepareBeanFactory
方法的源码,可以看出其设计的合理性和分工明确。
观察该方法可以看到其主要涉及的几部分:
设置基本属性
- 设置类加载器:
beanFactory.setBeanClassLoader(getClassLoader());
- 设置表达式解析器:
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
- 设置属性编辑器:
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
忽略特定依赖接口:
- 忽略自动装配的接口,如
EnvironmentAware
、ResourceLoaderAware
等:beanFactory.ignoreDependencyInterface(...)
注册可解析的依赖:
- 将特定接口与实例关联,以便在自动装配时使用这些实例:
beanFactory.registerResolvableDependency(...)
添加后置处理器:
- 添加
ApplicationContextAwareProcessor
:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
- 添加
ApplicationListenerDetector
:beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
- 处理
LoadTimeWeaver
:beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
注册默认的环境变量 Bean:
- 注册环境变量、系统属性和系统环境变量:
beanFactory.registerSingleton(...)
三、设置基本属性深入分析
(一)设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
直接功能为 BeanFactory
设置类加载器,确保在创建和加载 Bean 类时使用正确的类加载器。这对应用程序在不同的环境中运行时(例如在不同的容器中或使用不同的类加载策略时)尤为重要。
getClassLoader()
方法通常返回当前上下文(ApplicationContext
)的类加载器。通过 setBeanClassLoader
方法,将这个类加载器设置给 BeanFactory
,使得 BeanFactory
在加载类时能使用正确的类加载器。
(二)设置表达式解析器
beanFactory.setBeanExpressionResolver(
new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
直接功能为BeanFactory
设置一个标准的表达式解析器,允许在 Spring 配置文件中使用表达式语言(例如 SpEL,Spring Expression Language)来进行动态值的解析和注入。
StandardBeanExpressionResolver
是 Spring 提供的一个默认实现,用于解析 #{}
表达式。通过 setBeanExpressionResolver
方法,将 StandardBeanExpressionResolver
实例设置给 BeanFactory
,使其能够解析和处理配置中的表达式。
StandardBeanExpressionResolver
需要一个类加载器来加载和解析表达式中的类,这里使用的是 BeanFactory
的类加载器。
(三)设置属性编辑器
beanFactory.addPropertyEditorRegistrar(
new ResourceEditorRegistrar(this, getEnvironment()));
直接功能为BeanFactory
注册一个属性编辑器注册器(PropertyEditorRegistrar
),确保在 Spring 容器中处理属性值转换时,能够使用正确的属性编辑器。这对于处理复杂类型的属性(例如,将字符串转换为资源类型)非常重要。
ResourceEditorRegistrar
是一个 PropertyEditorRegistrar
的实现,用于注册与资源相关的属性编辑器。ResourceEditorRegistrar
需要两个参数:ResourceLoader
和 Environment(这部分回顾可见
重看Spring聚焦Environment分析-CSDN博客)
。
this
代表当前的ApplicationContext
,它实现了ResourceLoader
接口。getEnvironment()
返回当前上下文的环境(Environment
),用于获取系统属性和环境变量。
通过 addPropertyEditorRegistrar
方法,将 ResourceEditorRegistrar
实例添加到 BeanFactory
中,从而注册相应的属性编辑器。
(四)设计目的分析
在 prepareBeanFactory
方法中,设置基本属性部分的代码为 BeanFactory
的初始化奠定了基础。通过设置类加载器、表达式解析器和属性编辑器,确保 BeanFactory
能够正确地加载类、解析配置中的表达式以及处理属性值的转换。这些设置对于 BeanFactory
在创建和管理 Bean 实例时的正常运作至关重要。
类加载器设置:保障 BeanFactory
在不同环境下的一致性和兼容性,使得 BeanFactory
能够在多模块或插件化的应用中正确加载类。
表达式解析器设置:提供了在配置文件中使用动态表达式的能力,增强了配置的灵活性和动态性。例如,可以使用 #{systemProperties['user.dir']}
动态获取系统属性。
属性编辑器设置:通过注册自定义的属性编辑器,确保在属性注入时能够进行复杂类型的转换。例如,可以将字符串路径转换为 Resource
类型,方便资源的加载和管理。
通过以上分析可以看出,prepareBeanFactory
中设置基本属性的部分为 BeanFactory
的后续操作提供了坚实的基础,确保其能够在各种复杂场景下正常工作。
四、忽略自动装配深入分析
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
(一)详细分析和说明
指定某些接口在自动装配过程中被忽略,防止这些接口被意外地自动装配到 Bean 中,这些接口通常由 Spring 框架内部使用,通过 Aware 接口注入 Spring 容器中的特定资源。
ignoreDependencyInterface
方法告诉 BeanFactory
在自动装配过程中忽略这些特定的接口。这些接口通常用于标识需要特定资源(如 Environment
、ResourceLoader
等)的 Bean,这些资源会在 Bean 初始化的过程中由 Spring 自动注入。忽略这些接口是为了确保它们不会通过常规的自动装配过程注入,而是通过 Spring 的特殊处理机制进行注入。
EnvironmentAware
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
实现 EnvironmentAware
接口的 Bean 可以通过 setEnvironment(Environment environment)
方法获取 Environment
对象。忽略原因:Environment
对象由 Spring 容器管理,通过 prepareBeanFactory
方法中的其他机制进行注入,而不是通过常规的自动装配机制。
EmbeddedValueResolverAware
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
实现 EmbeddedValueResolverAware
接口的 Bean 可以通过 setEmbeddedValueResolver(StringValueResolver resolver)
方法获取 StringValueResolver
对象,用于解析嵌入的字符串值(如 ${}
占位符)。忽略原因:StringValueResolver
通常在 Spring 配置解析时使用,需要由 Spring 自动注入而不是通过自动装配。
ResourceLoaderAware
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
实现 ResourceLoaderAware
接口的 Bean 可以通过 setResourceLoader(ResourceLoader resourceLoader)
方法获取 ResourceLoader
对象,用于加载外部资源。忽略原因:ResourceLoader
通常由 Spring 容器提供,用于统一资源加载机制,应由 Spring 自动注入。
ApplicationEventPublisherAware
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
实现ApplicationEventPublisherAware
接口的 Bean 可以通过 setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
方法获取ApplicationEventPublisher
对象,用于发布应用事件。忽略原因:ApplicationEventPublisher
是 Spring 事件发布机制的一部分,需要由 Spring 容器自动注入。
MessageSourceAware
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
实现 MessageSourceAware接口的 Bean 可以通过 setMessageSource(MessageSource messageSource)方法获取MessageSource对象,用于国际化消息的解析。
忽略原因:MessageSource 由 Spring 管理,用于处理国际化消息,应由 Spring 自动注入。
ApplicationContextAware
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
实现 ApplicationContextAware
接口的 Bean 可以通过 setApplicationContext(ApplicationContext applicationContext)
方法获取 ApplicationContext
对象,进而访问 Spring 容器本身。忽略原因:ApplicationContext
是 Spring 容器的核心接口,需要由 Spring 容器自动注入,而不是通过常规的自动装配机制。
(二)设计目的分析
在 prepareBeanFactory
方法中,忽略特定依赖接口的代码部分主要是为了确保这些特殊的 Aware 接口由 Spring 容器内部机制注入,而不是通过常规的自动装配机制注入。这些接口通常用于获取 Spring 容器中的特定资源(如 Environment
、ResourceLoader
、ApplicationContext
等),这些资源的注入需要由 Spring 框架来管理,以确保正确的依赖关系和资源管理。
通过忽略这些接口,可以防止它们在自动装配过程中被误注入,从而确保 Spring 容器的正确初始化和运行。
五、注册可解析的依赖深入分析
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
(一)详细分析和说明
将特定接口与相应的实例关联,以便在自动装配时能够使用这些预定义的实例,确保在 Spring 容器中,这些核心接口可以在自动装配过程中被正确解析并注入相应的实例。这些接口通常是 Spring 框架自身需要管理和使用的。
registerResolvableDependency
方法允许将一个接口与一个特定的实例关联起来,当自动装配需要该接口的实现时,Spring 会自动使用预先注册的实例。
通过这种方式,可以确保这些关键的 Spring 内部接口在需要时能够被正确注入,而不需要额外的配置。
注册 BeanFactory
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
将 BeanFactory.class
接口与当前的 beanFactory
实例关联,确保在需要自动装配 BeanFactory
接口时,能够注入当前的 beanFactory
实例。这对于在 Bean 中需要访问或操作 BeanFactory
的场景非常有用。通过 registerResolvableDependency
方法,Spring 容器会将 BeanFactory
接口解析为当前的 beanFactory
实例。
注册 ResourceLoader
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
将 ResourceLoader.class
接口与当前的 ApplicationContext
实例(this
)关联,确保在需要自动装配 ResourceLoader
接口时,能够注入当前的 ApplicationContext
实例。ApplicationContext
本身实现了 ResourceLoader
接口,提供统一的资源加载机制。通过 registerResolvableDependency
方法,Spring 容器会将 ResourceLoader
接口解析为当前的 ApplicationContext
实例。
注册 ApplicationEventPublisher
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
将 ApplicationEventPublisher.class
接口与当前的 ApplicationContext
实例(this
)关联,确保在需要自动装配 ApplicationEventPublisher
接口时,能够注入当前的 ApplicationContext
实例。ApplicationContext
本身实现了 ApplicationEventPublisher
接口,提供事件发布功能。通过 registerResolvableDependency
方法,Spring 容器会将 ApplicationEventPublisher
接口解析为当前的 ApplicationContext
实例。
注册 ApplicationContext
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
将 ApplicationContext.class
接口与当前的 ApplicationContext
实例(this
)关联,确保在需要自动装配 ApplicationContext
接口时,能够注入当前的 ApplicationContext
实例。这样可以使 Bean 直接访问 Spring 容器的功能。通过 registerResolvableDependency
方法,Spring 容器会将 ApplicationContext
接口解析为当前的 ApplicationContext
实例。
(二)设计目的分析
在 prepareBeanFactory
方法中,注册可解析的依赖部分的代码通过 registerResolvableDependency
方法,将一些关键的 Spring 内部接口与相应的实例关联起来。
- 确保自动装配的准确性:通过注册这些可解析的依赖,可以确保在自动装配过程中,这些核心接口能够被正确解析并注入预定义的实例,避免了手动配置的麻烦。
- 提供核心接口的便捷访问:这些接口(如
BeanFactory
、ResourceLoader
、ApplicationEventPublisher
、ApplicationContext
)通常在复杂应用中被频繁使用,通过这种方式可以简化开发过程,提供便捷的访问。 - 增强 Spring 容器的灵活性:这种设计使得 Spring 容器更加灵活和健壮,可以更好地管理和注入这些关键的依赖,提供更高的可维护性和可靠性。
prepareBeanFactory
方法中注册可解析的依赖部分,通过将关键的 Spring 内部接口与特定实例关联,确保这些接口在自动装配过程中能够被正确解析和注入。这不仅简化了配置,还增强了 Spring 容器的灵活性和可靠性。通过这种方式,开发者可以更方便地使用这些核心接口,提升开发效率和代码质量。
六、添加后置处理器深入分析
(一)添加 ApplicationContextAwareProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
为 BeanFactory
添加一个 ApplicationContextAwareProcessor
后置处理器,确保实现 ApplicationContextAware
接口的 Bean 能够获得 ApplicationContext
实例。
ApplicationContextAwareProcessor
实现了 BeanPostProcessor
接口,它会在 Bean 初始化的过程中处理实现 ApplicationContextAware
、EnvironmentAware
、ResourceLoaderAware
、ApplicationEventPublisherAware
等接口的 Bean。
具体来说,ApplicationContextAwareProcessor
会在 Bean 初始化时调用相应的 setApplicationContext
、setEnvironment
、setResourceLoader
、setApplicationEventPublisher
方法,将当前的 ApplicationContext
、Environment
、ResourceLoader
和 ApplicationEventPublisher
注入到 Bean 中。
(二)添加 ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
为 BeanFactory
添加一个 ApplicationListenerDetector
后置处理器,检测实现 ApplicationListener
接口的 Bean,并将其注册到 ApplicationEventMulticaster
中,以便监听应用事件。
ApplicationListenerDetector
实现了 BeanPostProcessor
接口,它会在 Bean 初始化之后检测 Bean 是否实现了 ApplicationListener
接口。
如果检测到某个 Bean 实现了 ApplicationListener
接口,ApplicationListenerDetector
会将该 Bean 注册到 ApplicationEventMulticaster
中,使其能够监听并处理应用事件。
(三)处理 LoadTimeWeaver
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
为 BeanFactory
添加一个 LoadTimeWeaverAwareProcessor
后置处理器,确保实现 LoadTimeWeaverAware
接口的 Bean 能够获得 LoadTimeWeaver
实例。
LoadTimeWeaverAwareProcessor
实现了 BeanPostProcessor
接口,它会在 Bean 初始化的过程中处理实现 LoadTimeWeaverAware
接口的 Bean。
具体来说,LoadTimeWeaverAwareProcessor
会在 Bean 初始化时调用 setLoadTimeWeaver
方法,将 LoadTimeWeaver
实例注入到 Bean 中。LoadTimeWeaver
用于在运行时动态地加载和织入类,这对于一些需要在运行时增强类的功能(例如 AOP)非常重要。
(四)设计目的分析
在 prepareBeanFactory
方法中,添加后置处理器部分的代码通过 addBeanPostProcessor
方法为 BeanFactory
添加了三个重要的后置处理器:ApplicationContextAwareProcessor
、ApplicationListenerDetector
和 LoadTimeWeaverAwareProcessor
。
- 确保关键接口的注入:
ApplicationContextAwareProcessor
确保了实现Aware
接口的 Bean 能够获得 Spring 容器中的关键组件(如ApplicationContext
、Environment
等)。LoadTimeWeaverAwareProcessor
确保了实现LoadTimeWeaverAware
接口的 Bean 能够获得LoadTimeWeaver
实例,用于运行时类加载和织入。 - 增强事件处理能力:
ApplicationListenerDetector
确保了实现ApplicationListener
接口的 Bean 能够注册到ApplicationEventMulticaster
中,从而能够监听和处理应用事件。这对于事件驱动的应用程序设计非常重要。 - 提高 Spring 容器的灵活性和可维护性:通过添加这些后置处理器,Spring 容器能够更好地管理和处理特殊类型的 Bean,提供更高的灵活性和可维护性。
prepareBeanFactory
方法中添加后置处理器部分,通过为 BeanFactory
添加 ApplicationContextAwareProcessor
、ApplicationListenerDetector
和 LoadTimeWeaverAwareProcessor
三个后置处理器,确保了 Spring 容器能够正确处理实现特定接口的 Bean。这些后置处理器的添加,使得 Spring 容器能够灵活地管理 Bean 的依赖注入和事件处理。
七、注册默认的环境变量 Bean深入分析
beanFactory.registerSingleton("environment", getEnvironment());
beanFactory.registerSingleton("systemProperties", getEnvironment().getSystemProperties());
beanFactory.registerSingleton("systemEnvironment", getEnvironment().getSystemEnvironment());
为 BeanFactory
注册几个默认的单例 Bean,用于环境变量、系统属性和系统环境变量的访问。使这些关键的环境信息可以作为 Spring 容器中的 Bean 被其他组件注入和使用,方便应用程序对环境信息的获取和管理。
registerSingleton
方法用于将一个特定的实例注册为单例 Bean。注册的 Bean 可以通过依赖注入的方式在其他 Bean 中使用,提供对环境信息的便捷访问。
(一)注册环境变量 Bean
beanFactory.registerSingleton("environment", getEnvironment());
将 Environment
实例注册为名为 "environment" 的单例 Bean,提供对 Spring 环境对象的访问,允许其他 Bean 通过注入 Environment
Bean 来获取和使用环境信息。
getEnvironment()
方法返回当前的 Environment
实例,Environment
接口提供了访问环境属性和配置文件的方法,是 Spring 环境抽象的重要组成部分。
通过 registerSingleton("environment", getEnvironment())
,将 Environment
实例注册到 BeanFactory
中,名称为 "environment"。
(二)注册系统属性 Bean
beanFactory.registerSingleton("systemProperties", getEnvironment().getSystemProperties());
将系统属性映射 (Map<String, Object>
) 注册为名为 "systemProperties" 的单例 Bean,提供对系统属性的访问,允许其他 Bean 通过注入 systemProperties
Bean 来获取和使用系统属性。
getEnvironment().getSystemProperties()
方法返回一个包含系统属性的映射。通过 registerSingleton("systemProperties", getEnvironment().getSystemProperties())
,将系统属性映射注册到 BeanFactory
中,名称为 "systemProperties"。
(三)注册系统环境变量 Bean
beanFactory.registerSingleton("systemEnvironment", getEnvironment().getSystemEnvironment());
将系统环境变量映射 (Map<String, Object>
) 注册为名为 "systemEnvironment" 的单例 Bean,提供对系统环境变量的访问,允许其他 Bean 通过注入 systemEnvironment
Bean 来获取和使用系统环境变量。
getEnvironment().getSystemEnvironment()
方法返回一个包含系统环境变量的映射。通过 registerSingleton("systemEnvironment", getEnvironment().getSystemEnvironment())
,将系统环境变量映射注册到 BeanFactory
中,名称为 "systemEnvironment"。
(四)设计目的分析
在 prepareBeanFactory
方法中,注册默认的环境变量 Bean 部分的代码通过 registerSingleton
方法为 BeanFactory
注册了三个重要的单例 Bean:environment
、systemProperties
和 systemEnvironment
。
- 确保环境信息的便捷访问:通过注册
Environment
、系统属性和系统环境变量为单例 Bean,Spring 容器中的其他 Bean 可以通过依赖注入轻松访问这些环境信息,提供了极大的便利性。 - 统一环境信息的管理:将这些环境信息注册为单例 Bean,提供了一个统一的管理方式,使得应用程序中的所有组件可以共享同一个
Environment
实例和相同的系统属性、系统环境变量。 - 提高配置和调试的灵活性:通过注入这些环境信息,我们可以在应用程序运行时动态访问和修改环境配置,有助于提高调试和配置的灵活性。
prepareBeanFactory
方法中注册默认的环境变量 Bean 部分,通过为 BeanFactory
注册 environment
、systemProperties
和 systemEnvironment
三个单例 Bean,确保了 Spring 容器中的其他组件可以方便地访问和使用这些关键的环境信息。
八、总结
通过 prepareBeanFactory
方法,Spring 框架为 BeanFactory
配置了一系列关键属性和处理器,使其具备了处理复杂 Bean 依赖和初始化过程的能力。这一步骤为应用上下文的后续处理奠定了坚实的基础,确保 Spring 容器能够高效、灵活地管理 Bean 的生命周期和依赖注入。通过这种设计,Spring 框架不仅增强了 BeanFactory
的功能,还提高了应用程序的可维护性和可扩展性,体现了其强大的设计思想和实现技巧。
从源码级别,具体的实现上我们可以总结出如下表格:
处理部分 | 描述 | 作用 |
设置基本属性 | 设置 BeanFactory 的类加载器、表达式解析器和属性编辑器。 | 确保 BeanFactory 能正确地加载类、解析表达式和处理属性。 |
忽略特定依赖接口 | 忽略自动装配的某些依赖接口,如 EnvironmentAware 、ResourceLoaderAware 等。 | 避免这些依赖接口被自动装配,从而在特定条件下避免不必要的依赖注入。 |
注册可解析的依赖 | 将一些关键接口与具体实例关联,以便在自动装配时使用这些实例。 | 确保这些核心接口可以在自动装配过程中被正确解析并注入相应的实例。 |
添加后置处理器 | 为 BeanFactory 添加后置处理器,如 ApplicationContextAwareProcessor 、ApplicationListenerDetector 和 LoadTimeWeaverAwareProcessor 。 | 确保在 Bean 初始化过程中处理特定类型的 Bean,如实现 ApplicationContextAware 、ApplicationListener 和 LoadTimeWeaverAware 接口的 Bean。 |
注册默认的环境变量 Bean | 为 BeanFactory 注册默认的单例 Bean,如环境变量、系统属性和系统环境变量。 | 使这些关键的环境信息可以作为 Spring 容器中的 Bean 被其他组件注入和使用。 |