聚焦IOC容器刷新环节prepareBeanFactory专项

news2024/9/22 7:31:37

目录

一、IOC容器的刷新环节快速回顾

二、prepareBeanFactory源码展示分析

三、设置基本属性深入分析

(一)设置类加载器

(二)设置表达式解析器

(三)设置属性编辑器

(四)设计目的分析

四、忽略自动装配深入分析

(一)详细分析和说明

EnvironmentAware

EmbeddedValueResolverAware

ResourceLoaderAware

ApplicationEventPublisherAware

MessageSourceAware

ApplicationContextAware

(二)设计目的分析

五、注册可解析的依赖深入分析

(一)详细分析和说明

注册 BeanFactory

注册 ResourceLoader

注册 ApplicationEventPublisher

注册 ApplicationContext

(二)设计目的分析

六、添加后置处理器深入分析

(一)添加 ApplicationContextAwareProcessor

(二)添加 ApplicationListenerDetector

(三)处理 LoadTimeWeaver

(四)设计目的分析

七、注册默认的环境变量 Bean深入分析

(一)注册环境变量 Bean

(二)注册系统属性 Bean

(三)注册系统环境变量 Bean

(四)设计目的分析

八、总结


干货分享,感谢您的阅读!

在很早之前我们单独写过一篇文章《分析SpringBoot启动配置原理》,具体可见:

解析SpringBoot启动配置原理icon-default.png?t=N7T8https://blog.csdn.net/xiaofeng10330111/article/details/130903779?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171829487016800213028572%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171829487016800213028572&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-130903779-null-null.nonecase&utm_term=%E5%88%86%E6%9E%90SpringBoot%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E5%8E%9F%E7%90%86&spm=1018.2226.3001.4450其中IOC容器的刷新环节可当重点分析,值得在读源码时进行深入分析,我们会从多个方向上再次进行分析回顾和学习。

一、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()));

忽略特定依赖接口

  • 忽略自动装配的接口,如 EnvironmentAwareResourceLoaderAware 等:beanFactory.ignoreDependencyInterface(...)

注册可解析的依赖

  • 将特定接口与实例关联,以便在自动装配时使用这些实例:beanFactory.registerResolvableDependency(...)

添加后置处理器

  • 添加 ApplicationContextAwareProcessorbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  • 添加 ApplicationListenerDetectorbeanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  • 处理 LoadTimeWeaverbeanFactory.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 需要两个参数:ResourceLoaderEnvironment(这部分回顾可见重看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 在自动装配过程中忽略这些特定的接口。这些接口通常用于标识需要特定资源(如 EnvironmentResourceLoader 等)的 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 容器中的特定资源(如 EnvironmentResourceLoaderApplicationContext 等),这些资源的注入需要由 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 内部接口与相应的实例关联起来。

  • 确保自动装配的准确性通过注册这些可解析的依赖,可以确保在自动装配过程中,这些核心接口能够被正确解析并注入预定义的实例,避免了手动配置的麻烦。
  • 提供核心接口的便捷访问这些接口(如 BeanFactoryResourceLoaderApplicationEventPublisherApplicationContext)通常在复杂应用中被频繁使用,通过这种方式可以简化开发过程,提供便捷的访问。
  • 增强 Spring 容器的灵活性这种设计使得 Spring 容器更加灵活和健壮,可以更好地管理和注入这些关键的依赖,提供更高的可维护性和可靠性。

prepareBeanFactory 方法中注册可解析的依赖部分,通过将关键的 Spring 内部接口与特定实例关联,确保这些接口在自动装配过程中能够被正确解析和注入。这不仅简化了配置,还增强了 Spring 容器的灵活性和可靠性。通过这种方式,开发者可以更方便地使用这些核心接口,提升开发效率和代码质量。

六、添加后置处理器深入分析

(一)添加 ApplicationContextAwareProcessor

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

BeanFactory 添加一个 ApplicationContextAwareProcessor 后置处理器,确保实现 ApplicationContextAware 接口的 Bean 能够获得 ApplicationContext 实例。

ApplicationContextAwareProcessor 实现了 BeanPostProcessor 接口,它会在 Bean 初始化的过程中处理实现 ApplicationContextAwareEnvironmentAwareResourceLoaderAwareApplicationEventPublisherAware 等接口的 Bean。

具体来说,ApplicationContextAwareProcessor 会在 Bean 初始化时调用相应的 setApplicationContextsetEnvironmentsetResourceLoadersetApplicationEventPublisher 方法,将当前的 ApplicationContextEnvironmentResourceLoaderApplicationEventPublisher 注入到 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 添加了三个重要的后置处理器:ApplicationContextAwareProcessorApplicationListenerDetectorLoadTimeWeaverAwareProcessor

  • 确保关键接口的注入ApplicationContextAwareProcessor 确保了实现 Aware 接口的 Bean 能够获得 Spring 容器中的关键组件(如 ApplicationContextEnvironment 等)。LoadTimeWeaverAwareProcessor 确保了实现 LoadTimeWeaverAware 接口的 Bean 能够获得 LoadTimeWeaver 实例,用于运行时类加载和织入。
  • 增强事件处理能力ApplicationListenerDetector 确保了实现 ApplicationListener 接口的 Bean 能够注册到 ApplicationEventMulticaster 中,从而能够监听和处理应用事件。这对于事件驱动的应用程序设计非常重要。
  • 提高 Spring 容器的灵活性和可维护性:通过添加这些后置处理器,Spring 容器能够更好地管理和处理特殊类型的 Bean,提供更高的灵活性和可维护性。

prepareBeanFactory 方法中添加后置处理器部分,通过为 BeanFactory 添加 ApplicationContextAwareProcessorApplicationListenerDetectorLoadTimeWeaverAwareProcessor 三个后置处理器,确保了 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:environmentsystemPropertiessystemEnvironment

  • 确保环境信息的便捷访问:通过注册 Environment、系统属性和系统环境变量为单例 Bean,Spring 容器中的其他 Bean 可以通过依赖注入轻松访问这些环境信息,提供了极大的便利性。
  • 统一环境信息的管理:将这些环境信息注册为单例 Bean,提供了一个统一的管理方式,使得应用程序中的所有组件可以共享同一个 Environment 实例和相同的系统属性、系统环境变量。
  • 提高配置和调试的灵活性:通过注入这些环境信息,我们可以在应用程序运行时动态访问和修改环境配置,有助于提高调试和配置的灵活性。

prepareBeanFactory 方法中注册默认的环境变量 Bean 部分,通过为 BeanFactory 注册 environmentsystemPropertiessystemEnvironment 三个单例 Bean,确保了 Spring 容器中的其他组件可以方便地访问和使用这些关键的环境信息。

八、总结

通过 prepareBeanFactory 方法,Spring 框架为 BeanFactory 配置了一系列关键属性和处理器,使其具备了处理复杂 Bean 依赖和初始化过程的能力。这一步骤为应用上下文的后续处理奠定了坚实的基础,确保 Spring 容器能够高效、灵活地管理 Bean 的生命周期和依赖注入。通过这种设计,Spring 框架不仅增强了 BeanFactory 的功能,还提高了应用程序的可维护性和可扩展性,体现了其强大的设计思想和实现技巧。

从源码级别,具体的实现上我们可以总结出如下表格:

处理部分描述作用
设置基本属性设置 BeanFactory 的类加载器、表达式解析器和属性编辑器。确保 BeanFactory 能正确地加载类、解析表达式和处理属性。
忽略特定依赖接口忽略自动装配的某些依赖接口,如 EnvironmentAwareResourceLoaderAware 等。避免这些依赖接口被自动装配,从而在特定条件下避免不必要的依赖注入。
注册可解析的依赖将一些关键接口与具体实例关联,以便在自动装配时使用这些实例。确保这些核心接口可以在自动装配过程中被正确解析并注入相应的实例。
添加后置处理器BeanFactory 添加后置处理器,如 ApplicationContextAwareProcessorApplicationListenerDetectorLoadTimeWeaverAwareProcessor确保在 Bean 初始化过程中处理特定类型的 Bean,如实现 ApplicationContextAwareApplicationListenerLoadTimeWeaverAware 接口的 Bean。
注册默认的环境变量 BeanBeanFactory 注册默认的单例 Bean,如环境变量、系统属性和系统环境变量。

使这些关键的环境信息可以作为 Spring 容器中的 Bean 被其他组件注入和使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1940036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速排序、快速选择算法、找最近公共祖先

快速排序&#xff08;用i和j双指针&#xff0c;左部分值小&#xff0c;当ij时&#xff0c;两部分按基准值已经排序好&#xff0c;将基准值放到j即可。 class Solution {public int[] sortArray(int[] nums) {sort(nums,0,nums.length-1);return nums;}void sort(int[] nums,int…

初阶数据结构的实现1 顺序表和链表

顺序表和链表 1.线性表1.1顺序表1.1.1静态顺序表&#xff08;不去实现&#xff09;1.1.2动态顺序表1.1.2.1 定义程序目标1.1.2.2 设计程序1.1.2.3编写代码1.1.2.3测试和调试代码 1.1.2 顺序表的问题与思考 1.2链表1.2.1链表的概念及结构1.2.1.1 定义程序目标1.2.1.2 设计程序1.…

51单片机嵌入式开发:15、STC89C52RC操作蜂鸣器实现一个music音乐播放器的音乐盒

STC89C52RC操作蜂鸣器实现一个music音乐播放器的音乐盒 1 概述2 蜂鸣器操作方法3 蜂鸣器发出音声4 硬件电路5 软件实现6 整体工程&#xff1a;7 总结 1 概述 要实现一个基于STC89C52RC单片机的音乐盒&#xff0c;可以按照以下步骤进行&#xff1a; &#xff08;1&#xff09;硬…

Golang | Leetcode Golang题解之第274题H指数

题目&#xff1a; 题解&#xff1a; func hIndex(citations []int) int {// 答案最多只能到数组长度left,right:0,len(citations)var mid intfor left<right{// 1 防止死循环mid(leftright1)>>1cnt:0for _,v:range citations{if v>mid{cnt}}if cnt>mid{// 要找…

ISO 14001:企业环境管理的黄金标准

在全球可持续发展潮流中&#xff0c;企业的环境责任愈发重要。ISO 14001环境管理体系&#xff0c;为各类企业提供了一条优化环境绩效的明路。无论企业规模大小&#xff0c;业务类型如何&#xff0c;ISO 14001都能帮助企业有效管理环境影响&#xff0c;实现绿色发展。 ISO 14001…

QT样式美化 之 qss入门

样例一 *{font-size:13px;color:white;font-family:"宋体"; }CallWidget QLineEdit#telEdt {font-size:24px;}QMainWindow,QDialog{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #1B2534, stop: 0.4 #010101,stop: 0.5 #000101, stop: 1.0 #1F2B…

【LeetCode】day17:654 - 最大二叉树, 617 - 合并二叉树, 700 - 二叉树搜索树中的搜索, 98 - 验证二叉搜索树

LeetCode 代码随想录跟练 Day17 654.最大二叉树617.合并二叉树700.二叉搜索树中的搜索98.验证二叉搜索树 654.最大二叉树 题目描述&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的…

PyCharm创建一个空的python项目

1.设置项目路径 2.配置python解释器 右下角可以选择always

提交(git-add git-commit git-push)

当修改好一个功能的时候&#xff0c;可以提交到远程仓库&#xff0c;这样就等于更新了一次版本&#xff0c;那么下次改修了文件的话&#xff0c;是跟这个版本做对比的 git status&#xff0c; 查看文件修改情况&#xff0c;git add 假如你只想提交1个文件&#xff0c;那么直接…

Python入门基础教程(非常详细)

现在找工作真的越来越难了&#xff01;今年更是难上加难 前几天在网上刷到这样一条热搜&#xff1a; #23岁找工作因年龄大被HR拒绝了# 是这个世界疯了还是我疯了&#xff1f; 合着只想要有20年以上工作经验的应届毕业生是吧 这好像就是现在的就业市场现状&#xff1a;“35岁…

【leetcode】二分查找本质

标题&#xff1a;【leetcode】二分查找本质 水墨不写bug 正文开始&#xff1a;&#xff08;点击题目标题转跳到OJ&#xff09; 目录 &#xff08;O&#xff09;前言* &#xff08;一&#xff09; 在排序数组中查找元素的第一个和最后一个位置 思路详解&#xff1a; 参考代…

cocos2d-x安装和项目

首先多方查找资料发现教程很简洁&#xff0c;发现对自己的操作方面没多大帮助&#xff0c;后来干脆去官网&#xff0c;好像也很简洁。基于这样一个原因&#xff0c;加上我首次碰cocos2d-x&#xff0c;决定记录一下整个流程&#xff0c;解决实际操作上的疑惑。 涉及的方面&…

数模·时间序列

时间序列思维导图 时间序列分析的方法 聚焦于趋势和季节变化 时间序列预测模型 时间序列平稳性 时间序列的平稳性是时间序列分析中的一个重要概念。一个时间序列如果是平稳的&#xff0c;意味着其统计性质&#xff08;如均值、方差、自相关等&#xff09;不随时间变化。 平稳性…

[计网04] 传输层和应用层 笔记 总结 万字详解

目录 传输层概述和功能 URL 和URI 端口号划分 套接字Socket UDP&#xff08;User Datagram Protocol&#xff09; UDP首部 UDP伪首部 TCP 三报文握手和四报文挥手 TCP&#xff08;Transmission Control Protocol&#xff09; TCP首部报文格式 TCP流量控制 cwnd&…

如何在 C# ASP.NET MVC 项目中实现 Memcached?

一.介绍 在现代 Web 应用程序中&#xff0c;性能和可扩展性至关重要。提高性能的有效方法之一是使用缓存。Memcached 是一种开源、高性能、分布式内存缓存系统&#xff0c;被广泛使用。本文将引导您在 C# ASP.NET MVC 项目中实现 Memcached。 二.什么是 Memcached&#xff1f;…

SpringBoot面试高频总结01

1. 什么是SpringBoot&#xff1f; SpringBoot是一个基于Spring框架的快速开发框架&#xff0c;它采用约定大于配置&#xff0c;自动装配的方式&#xff0c;可以快速地创建独立的&#xff0c;生产级别的&#xff0c;基于Spring的应用程序。 相比于传统的Spring框架&#xff0c;S…

真实测评,霍尼韦尔、希喂、352宠物空气净化器性能对比

在快节奏的社会生活中&#xff0c;人们越来越注重精神需要&#xff0c;许多年轻人纷纷选择拥抱宠物&#xff0c;作为生活中的温馨伴侣。宠物们治愈心灵的同时也要付出一定“代价”&#xff0c;日常养护&#xff0c;如清理猫毛、管理气味以及保持宠物环境的清洁&#xff0c;都是…

Agent类型解析:AIGC在不同领域的应用与影响

目录 引言 垂直智能体&#xff08;Vertical Agent&#xff09; 水平智能体&#xff08;Horizontal Agent&#xff09; 混合智能体&#xff08;Hybrid Agent&#xff09; 结论 引言 在人工智能&#xff08;AI&#xff09;领域&#xff0c;智能体&#xff08;Agent&#xf…

更加深入Mysql-04-MySQL 多表查询与事务的操作

文章目录 多表查询内连接隐式内连接显示内连接 外连接左外连接右外连接 子查询 事务事务隔离级别 多表查询 有时我们不仅需要一个表的数据&#xff0c;数据可能关联到俩个表或者三个表&#xff0c;这时我们就要进行夺标查询了。 数据准备&#xff1a; 创建一个部门表并且插入…

JavaWeb day01-HTML入门

Web前端 课程安排 HTML、CSS简介 HTML快速入门 实现标题排版 新闻标题样式