Spring底层如何执行?

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • Spring底层如何执行
    • refresh()
      • prepareRefresh() 准备刷新的工作
        • initPropertySources()
      • obtainFreshBeanFactory()
        • refreshBeanFactory()
          • AbstractRefreshableApplicationContext 实现
          • GenericApplicationContext 实现
      • prepareBeanFactory() 准备BeanFactory
      • postProcessBeanFactory()
      • invokeBeanFactoryPostProcessors()
        • PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
      • registerBeanPostProcessors()
      • initMessageSource()
      • initApplicationEventMulticaster()
      • onRefresh()
      • registerListeners()
      • finishBeanFactoryInitialization()
      • finishRefresh()
  • 总结


Spring底层如何执行

首先定义了application.xml在这里插入图片描述
接下来我们来看下 BeanFactory context = new ClassPathXmlApplicationContext(“application.xml”); 内部是如何执行的
在这里插入图片描述

refresh()

回想下Spring的基本运行流程,想一想我们第一步应该做什么?
第一步是创建我们的BeanFactory对象

@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.//准备刷新上下文环境。作用就是初始化一些状态和属性,为后面的工作做准备。prepareRefresh();// Tell the subclass to refresh the internal bean factory.//告诉子类刷新内部bean工厂。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.//对beanFactory进行一些初始化工作prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.// 对 BeanFactory 做额外处理。默认没有实现postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.// 激活各种BeanFactory后处理器invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// 注册并创建拦截bean创建的(BeanPostProcessors) bean处理器registerBeanPostProcessors(beanFactory);// Initialize message source for this context.// 为上下文初始化Message源,即不同语言的消息体,国际化处理initMessageSource();// Initialize event multicaster for this context.// 初始化应用消息广播器,并放入"applicationEventMulticaster" bean 中,用来发布监听事件initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.// 将各种类型的监听器注册到应用事件广播器中,以便它们能够接收和处理应用程序中产生的事件registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

prepareRefresh() 准备刷新的工作

初始化前的准备工作,对系统属性或者环境变量进行准备及验证。在某些情况下项目的使用需要读取某些系统变量,那么在启动时候,就可以通过准备函数来进行参数的校验。
在这里插入图片描述

  1. 设置上下文的启动日期和激活标志,将 startupDate 设置为当前时间戳,将 closed 标志设为false(表示上下文未关闭),将 active 标志设为 true(表示上下文处于活动状态)
  2. 如果日志记录级别为调试模式,它会打印出“Refreshing”和应用程序上下文的显示名称
  3. 在上下文环境中初始化任何占位符属性源。这个步骤可以理解为加载和准备上下文所需的配置属性,例如从属性文件中读取配置项。
  4. 验证所有标记为(必需)的属性是否可解析。这是为了确保应用程序上下文所需的属性在配置中可用,并通过验证确保了属性的正确性和有效性。
public void validateRequiredProperties() {//创建一个 MissingRequiredPropertiesException 异常对象,用于收集缺失的必需属性MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException(); //遍历 requiredProperties 集合中的每个属性键Iterator var2 = this.requiredProperties.iterator();while(var2.hasNext()) {String key = (String) var2.next();if (this.getProperty(key) == null) {//为空,将该属性键添加到 MissingRequiredPropertiesException 对象中的缺失属性列表ex.addMissingRequiredProperty(key);}}//主要目的是验证在应用程序上下文中标记为必需的属性是否在配置中已解析。如果有任何缺失的必需属性,则会抛出异常if (!ex.getMissingRequiredProperties().isEmpty()) {throw ex;}
}
initPropertySources()

这个方法是为了给用户自己实现初始化逻辑,可以初始化一些属性资源。因此Spring并没有实现这个方法
在这里插入图片描述

obtainFreshBeanFactory()

obtainFreshBeanFactory() 从字面意思就是获取BeanFactory,这个方法的作用是刷新上下文的内部 BeanFactory。它会调用 refreshBeanFactory() 方法来重新加载配置,并返回刷新后的 BeanFactory 实例
obtainFreshBeanFactory() 方法应该涉及 BeanFactory 的实例化,以确保获得一个全新的 BeanFactory 实例
在这里插入图片描述

refreshBeanFactory()

此方法是一个抽象方法,需要由子类实现。子类负责执行实际的配置加载操作。该方法将在 refresh() 方法中的其他初始化工作之前调用。
负责刷新上下文的 BeanFactory。它会关闭之前的 BeanFactory(如果有),创建一个新的 BeanFactory,并加载配置信息。这个步骤是 Spring 上下文初始化的关键,确保上下文中的 beans 和配置是最新的
两种方式实现该方法:

  • 要么创建一个新的 BeanFactory 并持有对它的引用
  • 要么返回它持有的单个 BeanFactory 实例。

如果多次刷新上下文,通常会抛出 IllegalStateException
在这里插入图片描述
BeanFactory的创建委托给了 refreshBeanFactory() 方法,refreshBeanFactory() 方法被两个类实现AbstractRefreshableApplicationContext 和 GenericApplicationContext。

AbstractRefreshableApplicationContext 实现

此实现执行此上下文的底层 BeanFactory 的实际刷新操作,(如果有)关闭先前的 BeanFactory,并为上下文的生命周期的下一个阶段初始化一个新的 BeanFactory。
在这里插入图片描述
在这里插入图片描述
loadBeanDefinitions(beanFactory); 执行后,这里可以看到我们加载的xml的BeanDefinition信息

GenericApplicationContext 实现

什么也不做:我们持有一个单个的内部 BeanFactory,依赖于调用者通过我们的公共方法(或 BeanFactory 的方法)注册 bean。
它会检查是否已经进行了刷新操作,如果已经刷新过了,则会抛出 IllegalStateException。此实现适用于那些只需要在初始化时设置 BeanFactory,而无需重新加载配置的情况。
在这里插入图片描述
这里可以看到,GenericApplicationContext 中的实现非常简单。只是简单的将刷新状态置为true。
需要注意的是 this.beanFactory 的实际类型为 DefaultListableBeanFactory。在GenericApplicationContext 的构造函数中进行了对象创建或指定。如下:
在这里插入图片描述

prepareBeanFactory() 准备BeanFactory

prepareBeanFactory() 对beanFactry 做了一些准备工作,设置了一些属性来扩展功能
该方法在初始化 BeanFactory 时会被调用,它确保上下文中的 beans 能够正确地处理,并配置了一些重要的特性和后置处理器
作用是配置 BeanFactory 的标准上下文特性,例如类加载器和后置处理器等等就是对上述创建的BeanFactory 空bean 做一些set注入。
我们这里看 AbstractApplicationContext#prepareBeanFactory 的实现。具体代码如下:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context's class loader etc.// 将当前上下文的类加载器getClassLoader设置为 BeanFactory 的类加载器beanFactory.setBeanClassLoader(getClassLoader());// 设置beanFactory 的表达式语言处理器,Spring3 增加了表达式语言的支持// 默认可以使用 #{bean.xxx}的形式来调用处理相关属性。beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));// 为beanFactory 增加一个默认的propertyEditor,这个主要是针对bean的属性等设置管理的一个工具,用于处理属性类型转换beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.// 添加 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 interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.// 设置了几个自动装配的特殊规则,这些类型的实例将作为特殊的解析依赖,可以在自动装配时自动注入beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// Register early post-processor for detecting inner beans as ApplicationListeners.// 注册用于检测内部 beans 是否为 ApplicationListeners 的后置处理器(ApplicationListenerDetector)beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.// 增加对 AspectJ的支持// 检测是否存在 LoadTimeWeaver 并进行相关配置。LoadTimeWeaver 可用于支持 AspectJ 类型的织入。if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {// 添加 LoadTimeWeaverAwareProcessor 作为后置处理器,用于处理实现了 LoadTimeWeaverAware 接口的 bean。beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.// 为类型匹配设置一个临时的 ClassLoader。这是由于在 LoadTimeWeaver 进行类型匹配时需要使用特殊的 ClassLoader。beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// Register default environment beans.// 添加默认的系统环境bean,检查是否已经注册了默认的环境 bean,如果没有,则将其注册为单例 beanif (!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());}}

postProcessBeanFactory()

对 BeanFactory 做额外处理。默认没有实现,是个空方法。
postProcessBeanFactory() 方法是在标准初始化之后修改应用程序上下文的内部 BeanFactory。在此阶段,所有的 bean 定义都已加载,但还没有实例化任何 bean。这允许在某些特定的 ApplicationContext 实现中注册特殊的 BeanPostProcessors 等。

这个方法的目的是对 BeanFactory 进行后续处理,根据需要进行一些自定义的配置。
例如,你可以注册一个 BeanFactoryPostProcessor,用于修改已加载的 bean 定义,进一步定制 BeanFactory 的行为。在这个方法中,你可以通过传入的 beanFactory 参数来访问和操作 BeanFactory 的各种属性和方法,以完成你的自定义逻辑。

注意:postProcessBeanFactory() 方法提供了在BeanFactory 初始化之后 但在 加载任何 bean 实例之前修改 BeanFactory 的机会。这个方法可以被用来修改 BeanFactory 的配置,例如添加额外的 BeanPostProcessor 实例或其他的自定义组件。但它一般不用于直接修改加载的 XML 或其他配置文件中的具体 bean 定义信息。

如果需要修改已经加载的 XML 或其他配置文件中的 bean 定义信息,更常见的做法是编写自定义的 BeanDefinitionRegistryPostProcessor。这个接口规定了在加载完 bean 定义后对它们进行修改的方法,例如修改 bean 的属性、添加或删除 bean 定义等。
在这里插入图片描述

invokeBeanFactoryPostProcessors()

主要是激活各种 BeanFactoryPostProcessors,处理bean的定义信息BeanDefinition,生成的注入容器中的bean 的 BeanDefinition
实例化并调用所有已注册的 BeanFactoryPostProcessor beans
在这里插入图片描述

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 调用 PostProcessorRegistrationDelegate 的 invokeBeanFactoryPostProcessors 方法// 传入 beanFactory 和已注册的 BeanFactoryPostProcessor 实例列表PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// 检测是否存在LoadTimeWeaver,并为织入操作做准备if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {// 创建 LoadTimeWeaverAwareProcessor 实例beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// 设置临时的类加载器beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()

用于实例化和调用所有已注册的 BeanFactoryPostProcessor 实例

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// Invoke BeanDefinitionRegistryPostProcessors first, if any.// 首先调用 BeanDefinitionRegistryPostProcessorSet<String> processedBeans = new HashSet<>();if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();// 遍历已注册的 BeanFactoryPostProcessor 实例for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {// 如果实现了 BeanDefinitionRegistryPostProcessor 接口,调用其 postProcessBeanDefinitionRegistry 方法BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);} else {// 否则,将其放入常规的后处理器列表中regularPostProcessors.add(postProcessor);}}// ...// 最后,调用之前收集到的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);} else {// ...// 如果不是 BeanDefinitionRegistry,则直接调用后处理器invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}// ...// 最后刷新 BeanFactory 的元数据缓存beanFactory.clearMetadataCache();
}

registerBeanPostProcessors()

注册并调用所有已注册的 BeanPostProcessor bean,遵循明确的顺序(如果有)必须在实例化应用程序 bean 之前调用。
注册所有的BeanPostProcessors beans 但是只是注册不会执行,这里执行提前说注册bean,提前把准备工作注册好。BeanPostProcessor 在这一步已经完成了创建

BeanFactoryPostProcessor :对没有实例化之前的BeanDefinition,对Bean的配置元数据进行操作
BeanPostProcessor :作用:在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的
在这里插入图片描述

在这里插入图片描述

/*** 注册并调用所有已注册的 BeanPostProcessor bean,遵循明确的顺序(如果有)。* <p>必须在实例化应用程序 bean 之前调用。*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// 获取所有注册的 BeanPostProcessor 的名称String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// 注册一个 BeanPostProcessorChecker,用于在 BeanPostProcessor 实例化期间创建 bean 时记录信息。// 如果一个 bean 不能被所有 BeanPostProcessor 处理,它会在这个检查器中进行标记。int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// 区分实现 PriorityOrdered、Ordered 和其它类型 BeanPostProcessor 的实例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);}}// 首先,注册实现 PriorityOrdered 接口的 BeanPostProcessor 实例。sortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// 接下来,注册实现 Ordered 接口的 BeanPostProcessor 实例。List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();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);// 现在,注册所有普通的 BeanPostProcessor 实例。List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// 最后,重新注册所有内部的 BeanPostProcessor 实例。sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);// 重新注册用于检测内部 bean 的后处理器作为 ApplicationListeners,并将其移动到处理器链的末尾(用于拾取代理等)。beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

initMessageSource()

为上下文初始化Message源,即不同语言的消息体,国际化处理

这里的作用很明显就是提取配置中定义的MessageSource,并将其记录在Spring容器中。如果用户没有设置资源文件,Spring提供了默认的配置 DelegatingMessageSource。
在这里Spring 通过 beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); 来获取名称为 MESSAGE_SOURCE_BEAN_NAME (messageSource) 的bean作为 资源文件。这里也体现出了Spring “约束大于规定”的原则。
在这里插入图片描述

initApplicationEventMulticaster()

初始化应用消息广播器,并放入"applicationEventMulticaster" bean 中,方便后续发布监听事件
initApplicationEventMulticaster 存在两种:

  1. 默认的事件广播器 ApplicationEventMulticaster
  2. 用户自定义的事件广播器

注意:
如果用户自定义了事件广播器,在使用用户自定义的事件广播器。
如果用户没有自定义事件广播器,则使用默认的 ApplicationEventMulticaster
在这里插入图片描述
在 SimpleApplicationEventMulticaster 中multicastEvent方法,可以看到,当Spring事件产生的时候,默认会使用multicastEvent 方法来广播事件,遍历给定事件类型的所有注册监听器,并使用监听器中的 onApplicationEvent 方法来进行监听事件的处理(通过 invokeListener 方法激活监听方法onApplicationEvent)。而对于每个监听器来说,其实都可以获取到产生的事件,但使用进行处理由监听器自己决定。

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {// 如果未提供事件类型,则解析事件类型ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));// 遍历给定事件类型的所有注册监听器for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {// 获取用于异步事件处理的任务执行器Executor executor = getTaskExecutor();// 如果存在任务执行器,则在单独的线程上执行监听器if (executor != null) {executor.execute(() -> invokeListener(listener, event));} else {// 如果没有任务执行器,则同步调用监听器invokeListener(listener, event);}}
}// 辅助方法,用于调用监听器,并处理错误(如果设置了ErrorHandler)
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = getErrorHandler();// 如果设置了ErrorHandler,则在try-catch块内调用监听器if (errorHandler != null) {try {doInvokeListener(listener, event);} catch (Throwable err) {// 使用指定的ErrorHandler处理错误errorHandler.handleError(err);}} else {// 如果未设置ErrorHandler,则在不处理错误的情况下调用监听器doInvokeListener(listener, event);}
}// 实际调用监听器的onApplicationEvent方法
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {// 调用监听器的onApplicationEvent方法listener.onApplicationEvent(event);} catch (ClassCastException ex) {// 处理ClassCastException,可能由未解析的泛型事件类型导致String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// 抑制异常,并记录非匹配事件类型的调试信息Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

onRefresh()

Initialize other special beans in specific context subclasses.
初始化特定上下文子类中的其他特殊bean。
在这里插入图片描述

registerListeners()

注册监听器,实例化之前要把我们的监听器,监听事件注册好。

/*** 将实现了 ApplicationListener 接口的 Bean 添加为监听器。* 不会影响其他非Bean的监听器的添加。*/
protected void registerListeners() {// 首先注册静态指定的监听器。for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// 在这里不要初始化 FactoryBeans:我们需要保持所有常规 Bean 未初始化,以便让后置处理器对它们应用。String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}// 现在我们终于有了一个多播器,可以发布早期应用程序事件了...Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}
}
  1. 注册静态指定的监听器:
    首先,方法通过 getApplicationListeners() 获取所有在配置中静态指定的监听器。
    然后,通过 addApplicationListener 将这些监听器添加到应用事件广播器(ApplicationEventMulticaster)中。

  2. 注册实现了 ApplicationListener 接口的 Bean
    接下来,方法通过 getBeanNamesForType 获取所有实现了 ApplicationListener 接口的 Bean 的名称
    然后,通过 addApplicationListenerBean 将这些 Bean 添加到应用事件广播器中。这样做的目的是让通过Spring容器管理的Bean成为应用程序的监听器。

  3. 发布早期应用程序事件
    最后,如果存在早期应用程序事件(earlyApplicationEvents),则通过 multicastEvent 方法发布这些事件
    这样做是为了确保在应用程序上下文初始化的早期阶段,已经产生的事件能够被监听器接收和处理。

总体来说,registerListeners() 方法的目的是将各种类型的监听器注册到应用事件广播器中,以便它们能够接收和处理应用程序中产生的事件。

finishBeanFactoryInitialization()

实例化剩下的非懒加载的单例
在这里插入图片描述

/*** 完成此上下文的Bean工厂的初始化,初始化所有剩余的单例Bean。*/
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));}// 如果没有Bean后置处理器(如PropertyPlaceholderConfigurer Bean)在之前注册任何嵌入值解析器,// 则注册一个默认的嵌入值解析器:主要用于解析注解属性值。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();
}

该方法的作用是完成Bean工厂的初始化,初始化所有剩余的单例Bean

  1. 初始化转换服务:如果Bean工厂中包含名为 CONVERSION_SERVICE_BEAN_NAME 的Bean,并且该Bean的类型是 ConversionService,则将其设置为Bean工厂的转换服务。

  2. 注册默认的嵌入值解析器:如果Bean工厂没有注册任何嵌入值解析器(embedded value resolver),则注册一个默认的嵌入值解析器。这个解析器主要用于解析注解属性值中的占位符。

  3. 提前初始化LoadTimeWeaverAware Bean:提前初始化实现了 LoadTimeWeaverAware 接口的Bean,以便尽早注册它们的转换器(transformers)。

  4. 停止使用临时类加载器进行类型匹配:停止使用临时类加载器(tempClassLoader)进行Bean的类型匹配。

  5. 允许缓存所有Bean定义元数据:允许缓存所有Bean定义的元数据,表示不再期望对Bean定义进行进一步的更改。

  6. 实例化所有剩余的单例Bean:实例化所有剩余的非延迟初始化的单例Bean。
    在这里插入图片描述

总体来说,finishBeanFactoryInitialization() 方法的目的是在Bean工厂初始化过程的最后阶段完成剩余单例Bean的初始化工作。

finishRefresh()

	/*** Finish the refresh of this context, invoking the LifecycleProcessor's* onRefresh() method and publishing the* {@link org.springframework.context.event.ContextRefreshedEvent}.*/protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).clearResourceCaches();// Initialize lifecycle processor for this context.initLifecycleProcessor();// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();// Publish the final event.publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);}

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ensp】VLAN间通信的解决办法

目录 VLAN间通信简介 VLAN间通信的两种方式 借助三层设备路由器进行VLAN间的通信&#xff08;也就是单臂路由&#xff09; 在端口上创建子接口之后为什么需要开启arp广播&#xff0c;是因为他是子接口吗? 拓扑图 交换机配置 路由器配置 查看路由器配置 测试能否实现…

Element-Ui的Form表单:Label文本两端对齐,且必填项的*不影响布局

1. HTML 结构 首先&#xff0c;确保你的 HTML 或 Vue 模板中有一个 el-form 组件&#xff0c;类似下面这样&#xff1a; <div id"app"><el-form :model"form" label-width"100px"><el-form-item label"用户名">&l…

基于springboot的医护人员排班系统

随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了医护人员排班系统的开发全过程。通过分析医护人员排班系统管理的不足&#xff0c;创建了一个计算机管理医护人员排班系统的方案。文章介绍了医护人员排班系统的系统分…

更改ip地址的几种方式有哪些

在数字化时代&#xff0c;IP地址作为网络设备的标识&#xff0c;对于我们在网络世界中的活动至关重要。然而&#xff0c;出于多种原因&#xff0c;如保护隐私、访问特定网站或进行网络测试&#xff0c;我们可能需要更改IP地址。虎观代理将详细介绍IP地址的更改方法与步骤&#…

【JavaSE】你真的了解内部类吗?

前言 本篇会详细讲解内部类的四种形式&#xff0c;让你掌握内部类~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 内部类介绍 实例内部类 定义 调用 静态内部类 定义 调用 匿名内部类 定义和调用1 调用方法2 …

预分频器×重装载值)/LSI频率 为什么等于总时间

1. 第一种算法理解&#xff1a;分频系数 64 &#xff0c;外部低速时钟40khz&#xff0c; 则一次计数周期1.6ms &#xff0c;计数625个数&#xff0c;则有625个周期 &#xff0c;1.6ms*625 等于1s 如果分频系数是64&#xff0c;外部低速时钟&#xff08;LSI&#xff09;频率是…

gitee和idea集成

1 集成插件 2 配置账号密码 3 直接将项目传到仓库 4直接从gitee下载项目

【CAN】采样点介绍及测试方法

文章目录 1 什么是采样点2 为什么需要采样点3 采样点的计算公式4 VH6501测试原理和方法4.1 VH6501测试采样点原理4.2 VH6501测试方法 >>返回总目录<< 1 什么是采样点 采样点是节点判断信号逻辑电平的位置&#xff0c;是CAN控制器读取总线电平&#xff0c;并解释各…

前端console用法分享

console对于前端人员来讲肯定都不陌生&#xff0c;相信大部分开发者都会使用console来进行调试&#xff0c;但它能做的绝不仅限于调试。 最常见的控制台方法 作为开发者&#xff0c;最常用的 console 方法如下&#xff1a; 控制台打印结果&#xff1a; 今天我分享的是一些 co…

网络爬虫:定义、应用及法律道德考量

网络爬虫技术在当今数据驱动的世界中发挥着重要作用。本文将从网络爬虫的定义和主要功能&#xff0c;其在业界的应用实例&#xff0c;以及涉及的法律和道德问题三个方面进行深入探讨。 1. 爬虫的定义和主要功能 网络爬虫&#xff0c;也称为网页爬虫或蜘蛛&#xff0c;是一种…

【C++对于C语言的扩充】函数重载、引用以及内联函数

文章目录 &#x1f680;前言&#x1f680;函数重载注意&#xff1a;✈️为什么C可以实现函数重载&#xff0c;而C语言却不行呢&#xff1f; &#x1f680;引用✈️引用的特性✈️C中为什么要引入引用✈️引用与指针的区别 &#x1f680;内联函数✈️内联函数特性 &#x1f680;…

【云计算】云数据中心网络(四):IPv6 网关

云数据中心网络&#xff08;四&#xff09;&#xff1a;IPv6 网关 1.什么是 IPv6 网关2.IPv6 网关设计思路3.IPv6 网关的主要应用场景3.1 IPv6 私网通信3.2 IPv6 互联网通信3.3 IPv6 互联网通信&#xff08;仅主动访问&#xff09; 1.什么是 IPv6 网关 2017 年&#xff0c;中国…

【十一】MyBatis Plus 原理分析

MyBatis Plus 原理分析 摘要 Java EE开发中必不可少ORM框架&#xff0c;目前行业里最流行的orm框架非Mybatis莫属了&#xff0c;而Mybatis框架本身没有提供api实现&#xff0c;所以市面上推出了Mybatis plus系列框架&#xff0c;plus版是mybatis增强工具&#xff0c;用于简化My…

JavaWeb前端/后端开发规范——接口文档概述及YApi平台的使用

前言&#xff1a; 整理下笔记&#xff0c;打好基础&#xff0c;daydayup!!! 接口文档 什么是接口文档&#xff1f; 目前主流的开发模式为前后端分离式开发&#xff0c;为了方便前后端的对接&#xff0c;就需要使用接口文件进行统一规范。 接口文档记载什么信息&#xff1f; 1&…

中国科学院大学学位论文LaTeX模版

Word排版太麻烦了&#xff0c;公式也不好敲&#xff0c;推荐用LaTeX模版&#xff0c;全自动 官方模版下载位置&#xff1a;国科大sep系统 → \rightarrow → 培养指导 → \rightarrow → 论文 → \rightarrow → 论文格式检测 → \rightarrow → 撰写模板下载百度云&#…

MongoDB爬虫:(某扑)实战

https://bbs.hupu.com/bxj网页地址: https://bbs.hupu.com/bxj 然后我们在网页上定义帖子名称、帖子链接、创建时间、回复数、最后回复用户...... 除此之外,我们发现虎扑步行街最多显示的页数(20): 、 当我们打开第3页的时候,网页的URL的地址变为了:https://bbs.hupu.…

交通部 JT/T 808(809 1076 1078 )车辆卫星定位系统 通信协议介绍

1 行业标准协议 1.1 官方网站 交通运输标准化信息系统 (mot.gov.cn) 附上官方下载地址&#xff1a; JT/T 808-2019 道路运输车辆卫星定位系统 终端通信协议及数据格式 JT/T 809-2019 道路运输车辆卫星定位系统 平台数据交换 JT/T 1076-2016 道路运输车辆卫星定位系统 车…

基于React Router6 TS实现路由守卫

定义路由表 import {BrowserRouter, Route, RouteObject, Routes,} from "react-router-dom"; import {Home, Login, NotFound} from "/views"; import {RouterGuard} from "/routers/router_guard.tsx"; import {ReactNode} from "react&…

基于Qt的二维码生成与识别

基于Qt的二维码生成与识别 一、获取QZxing开源库 1.通过封装的QZxing开源库生成和识别二维码&#xff0c;下载地址&#xff1a;GitCode - 开发者的代码家园https://gitcode.com/mirrors/ftylitak/qzxing/tree/master。 2.下载解压后&#xff0c;使用Qt Creator xx&#xff0…