Spring底层如何执行?

news2024/11/27 20:33:53

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

文章目录

  • 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对象

@Override
	public 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,如果没有,则将其注册为单例 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());
		}
	}

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.
	// 首先调用 BeanDefinitionRegistryPostProcessor
	Set<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.coloradmin.cn/o/1599546.html

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

相关文章

博客系统项目测试(selenium+Junit5)

在做完博客系统项目之后&#xff0c;需要对项目的功能、接口进行测试&#xff0c;利用测试的工具&#xff1a;selenium以及Java的单元测试工具Junit进行测试&#xff0c;下面式测试的思维导图&#xff0c;列出该项目需要测试的所有测试用例&#xff1a; 测试结果&#xff08;全…

链表拓展之双向链表

前言 在前面已经总结了单链表&#xff0c;有了单链表的基础会很好理解双链表的实现&#xff0c;忘记了可以跳转——>http://t.csdnimg.cn/GFPk9 接下来就由我带着各位看官来认识今天的主角吧~ 什么是双向链表 在单链表的基础上&#xff0c;它有两个方向的链接&#xff0c;一…

SpringBlade dict-biz/list SQL 注入漏洞复现

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

一文看懂动态IP代理API

“动态”意味着每次连接或每隔一段时间&#xff0c;用户的IP地址都会发生改变。由于IP地址的不断变化&#xff0c;用户可以避免因频繁访问同一网站而导致的IP被封锁的问题。API叫做应用程序接口&#xff0c;是一种让软件之间相互通信的接口。API允许用户通过编程方式来调用动态…

【从浅学到熟知Linux】进程控制下篇=>进程程序替换与简易Shell实现(含替换原理、execve、execvp等接口详解)

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 进程程序替换什么是程序替换及其原理替换函数execlexeclpexecleexecvexecvpexecvpeexecve 替换函数总结实现…

转行或者跳槽入职一家新公司,应该如何快速上手工作?

不管是干测试也好或者其它任何职业&#xff0c;没有谁会在一家公司待一辈子&#xff0c;转行不一定&#xff0c;但是跳槽是每一个打工人早晚都会面临的事情&#xff0c;今天就来跟大家聊聊这件事~ 入职一家新公司&#xff0c;你应该做什么可以最快速的上手工作&#xff1f; 这…

Python编程之旅:深入探索强大的容器——列表

在Python编程的世界中&#xff0c;容器&#xff08;Containers&#xff09;是一种用于存储多个项目的数据结构。其中&#xff0c;列表&#xff08;List&#xff09;是最常用且功能强大的容器之一。无论是初学者还是资深开发者&#xff0c;掌握列表的使用方法和技巧都是提升Pyth…

判断位数、按位输出、倒序输出(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int number 0;int i 1;int m 0;int z 0;int z1 0, z2 0, z3 0, z4 0;//提示用户&#xff1b;printf("请输…

电动汽车退役锂电池SOC主动均衡控制MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 仿真简介 模型选用双向反激变换器作为主动均衡拓扑电路&#xff0c;均衡策略采用基于SOC的主动均衡策略&#xff0c;旨在解决电动汽车退役锂电池的不一致性问题。模型选用双向反激变换器作为主动均衡拓扑电路…

27.8k Star,AI智能体项目GPT Pilot:第一个真正的人工智能开发者(附部署视频教程)

作者&#xff1a;Aitrainee | AI进修生 排版太难了&#xff0c;请点击这里查看原文&#xff1a;27.8k Star&#xff0c;AI智能体项目GPT Pilot&#xff1a;第一个真正的人工智能开发者&#xff08;附部署视频教程&#xff09; 今天介绍一下一个人工智能智能体的项目GPT Pilot。…

关于idea中mybatis插件,下载后,无法生成代码模板--解决方法

一、不用相信网上其他解决方法 1.1试过&#xff0c;无效 二、解决方法 2.1【注&#xff1a;多试几次】重新下载&#xff0c;并重新启动idea 三、操作方法 3.1步骤 3.2idea重启&#xff0c;【如果没有重启】手动重启&#xff0c;必须有&#xff0c;很重要 3.3重新下载mybat…

试题 C: 质因数个数

萎了&#xff0c;整个人都萎了 快三天都没刷题了&#xff0c;想着明天就蓝桥杯了&#xff0c;就找了个真题做了下 可以看得出来这题很简单 但是没有测试点给我用&#xff0c;所以我的代码不保证正确性 代码如下&#xff1a; #include<cstdio> #include<cmath> …

2024 年10个最佳 Ruby 测试框架

QA一直在寻找最好的自动化测试框架&#xff0c;这些框架提供丰富的功能、简单的语法、更好的兼容性和更快的执行速度。如果您选择结合使用Ruby和Selenium进行Web测试&#xff0c;可能需要搜索基于Ruby的测试框架进行Web应用程序测试。 Ruby测试框架提供了广泛的功能&#xff0…

备忘录模式:恢复对象状态的智能方式

在软件开发中&#xff0c;备忘录模式是一种行为型设计模式&#xff0c;它允许捕获并外部化对象的内部状态&#xff0c;以便在未来某个时刻可以将对象恢复到此状态。这种模式是撤销操作或者回滚操作的关键实现机制。本文将详细介绍备忘录模式的定义、实现、应用场景以及优缺点。…

【产品经理修炼之道】- 产品经理如何做用户行为分析

一、为什么要做用户行为分析 观点一&#xff1a;有些功能整个平台用户都希望做&#xff0c;是没有必要耗费人力评估的&#xff0c;只要做了就可以了。用户行为分析是形式&#xff0c;不能为了分析而分析。观点二&#xff1a;我都在这个行业做了这么多年了&#xff0c;用户需要…

掼蛋小技巧(上篇)

一、一火保两单 如果手中的牌可以组成同花顺并且不会造成两张以上的单牌&#xff0c;我们就可以组成同花顺&#xff1b;如果组了同花顺后有两张以上的单张则果断放弃组同花顺。 二、十张出一对&#xff0c;九张出单张 掼蛋残局的时候&#xff0c;如果判断出下家手上只有一个四头…

pyqt的人脸识别 基于face_recognition库

参考文献&#xff1a; 1、python face_recognition实现人脸识别系统_python facerecognition检测人脸-CSDN博客 2、cv2.VideoCapture()_cv2.videocapture(0)-CSDN博客 1、camera.py文件代码如下&#xff1b;目录如下 import sys from PyQt5.QtWidgets import QApplication, …

JVM主要知识点详解

目录 1. 性能监控和调优 1.1 调优相关参数 1.2 内存泄漏排查 1.3 cpu飙⾼ 2. 内存与垃圾回收 2.1JVM的组成&#xff08;面试题&#xff09; 2.2 Java虚拟机栈的组成 2.3 本地方法栈 2.4 堆 2.5 方法区&#xff08;抽象概念&#xff09; 2.5.1 方法区和永久代以及元空…

listpack

目录 为什么有listpack? listpack结构 listpack的节点entry 长度length encoding编码方式 listpack的API 1.创建listpack 2.遍历操作 正向遍历 反向遍历 3.查找元素 4.插入/替换/删除元素 总结 为什么有listpack? ziplist是存储在连续内存空间&#xff0c;节省…

两部电话机怎样能实现对讲?直接连接能互相通话吗?门卫门房传达室岗亭电话怎么搞?

目录 两部电话机能直接连接吗&#xff1f;用三通头分出来一条电话线两部电话机用一根电话线直接连接能互相通话吗&#xff1f; 什么电话机可以直接连接两部IP电话机&#xff08;网络电话机&#xff09;可以直接连接两部普通电话机之间通过一个电话交换机也可以连接跨区域的两部…