当前位置: 首页 > article >正文

Spring源码之refresh

1.refesh的核心介绍

在 Spring 框架中,refresh 主要用于刷新应用上下文。这一过程涉及多个重要的步骤,确保 Spring 容器的状态更新、bean 的加载以及资源的初始化。

refresh 方法的主要功能

  1. 初始化上下文

    refresh 方法会初始化应用上下文,加载和配置所有的 bean,包括从配置文件、注解、XML 等中定义的 bean。
  2. 注册后处理器

    在刷新过程中,Spring 会注册各种后处理器(如 BeanPostProcessor 和 BeanFactoryPostProcessor),这些后处理器可以对 bean 的创建过程进行干预。
  3. 执行初始化逻辑

    对于那些标记了 @PostConstruct 或实现了 InitializingBean 接口的 bean,Spring 会在此阶段调用它们的初始化方法。
  4. 创建和注册 bean

    在刷新过程中,Spring 会创建所有单例 bean 的实例并将其注册到应用上下文中。这包括处理依赖注入和自动装配。
  5. 处理生命周期事件

    在上下文刷新期间,Spring 会触发相应的生命周期事件,如 ContextRefreshedEvent,让其他组件可以监听这些事件并执行特定操作。

2.register源码

处理 bean 的定义、作用域、注解等信息,并将其注册到 Spring 的 bean 注册表中。AnnotatedBeanDefinitionReader#doRegisterBean()

3.refresh源码

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 这里会判断能否刷新,并且返回一个BeanFactory, 刷新不代表完全情况,主要是先执行Bean的销毁,然后重新生成一个BeanFactory,再在接下来的步骤中重新去扫描等等
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 准备BeanFactory
			// 1. 设置BeanFactory的类加载器、SpringEL表达式解析器、类型转化注册器
			// 2. 添加三个BeanPostProcessor,注意是 具体的BeanPostProcessor实例对象
			// 3. 记录ignoreDependencyInterface
			// 4. 记录ResolvableDependency
			// 5. 添加三个单例Bean
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 子类来设置一下BeanFactory
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

				// Invoke factory processors registered as beans in the context.
				// BeanFactory准备好了之后,执行BeanFactoryPostProcessor,开始对BeanFactory进行处理
				// 默认情况下:
				// 此时beanFactory的beanDefinitionMap中有6个BeanDefinition,5个基础BeanDefinition+AppConfig的BeanDefinition
				// 而这6个中只有一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor
				// 这里会执行ConfigurationClassPostProcessor进行@Component的扫描,扫描得到BeanDefinition,并注册到beanFactory中
				// 注意:扫描的过程中可能又会扫描出其他的BeanFactoryPostProcessor,那么这些BeanFactoryPostProcessor也得在这一步执行
				invokeBeanFactoryPostProcessors(beanFactory);  // scanner.scan()

				// Register bean processors that intercept bean creation.
				// 将扫描到的BeanPostProcessors实例化并排序,并添加到BeanFactory的beanPostProcessors属性中去
				registerBeanPostProcessors(beanFactory);

				beanPostProcess.end();

				// Initialize message source for this context.
				// 设置ApplicationContext的MessageSource,要么是用户设置的,要么是DelegatingMessageSource
				initMessageSource();

				// Initialize event multicaster for this context.
				// 设置ApplicationContext的applicationEventMulticaster,要么是用户设置的,要么是SimpleApplicationEventMulticaster
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 给子类的模板方法
				onRefresh();

				// Check for listener beans and register them.
				// 把定义的ApplicationListener的Bean对象,设置到ApplicationContext中去,并执行在此之前所发布的事件
				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();
				contextRefresh.end();
			}
		}
	}

3.1.首先是prepareRefresh方法

1.1initPropertySources模板方法,留给子类重写,

1.2validateRequiredProperties,从Environment中拿出key-value,包含系统环境变量和jvm环境变量,这个函数来验证目前需要使用到的key是否存在,如果不存在则报出异常。

说明:validateRequiredProperties 方法的主要作用是验证一组必需属性是否已被正确设置。通过抛出异常,它可以有效地提醒开发者或运维人员缺失的配置,从而提高应用的健壮性和可靠性。

1.3设置成员属性,主要是监听器。

// Initialize any placeholder property sources in the context environment.
		// 比如子类可以把ServletContext中的参数对设置到Environment
		// 模板方法
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

3.2obtainFreshBeanFactory

这里会判断能否刷新,并且返回一个BeanFactory,刷新不代表完全情况。主要是先执行Bean的销毁,然后重新生成一个BeanFactory,再在接下来的步骤中重新去扫描等等。

对于SpringBoot,使用容器是AnnotationConfigApplicationContext,不能重复刷新;

对于SpringMVC,使用的是AnnotationConfigWebApplicationContext,可以重复刷新;

并且,这两个容器的初始化时机不同,SpringBoot在this中初始化容器,而SpringMVC是在刷新的时候进行初始化。

3.3prepareBeanFactory--准备BeanFactory

// Spring5.3中新增的功能,可以选择是否开启Spel功能,shouldIgnoreSpel默认为false,表示开启
		if (!shouldIgnoreSpel) {	//  @Value(#{xxx})的解析器
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		}

		// 添加一个ResourceEditorRegistrar,注册一些级别的 类型转化器
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		// 组成一个BeanPostProcessor,用来处理EnvironmentAware、EmbeddedValueResolverAware等回调
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

3.1拿到BeanClassLoader,我们可以自己给Bean工厂设置类加载器

3.2设置SpringEL的解析器,#{XXX}

3.3设置类型转换器ResourceEditorRegistrar,里面有很多转换器,比如Spring字符串-->File文件

3.4添加ApplicationContextAwareProcessor到BeanPostProcessor中,处理Aware的回调,它已经添加到BeanPostProcessor的list当中

比如,一个方法实现了Aware接口,那么在创建完bean的时候,就会调用方法中重写了接口的方法。

3.5ignoreDependencyInterface

将需要忽略的放入集合当中,在自动注入(依赖注入)的时候,如果类实现了这些接口,那么依赖注入就不会调用set方法执行,而只在最后执行一次set方法

3.6registerResolvableDependency

将这些东西直接注册为bean,类型对应

3.7添加ApplicationListenerDetector,它已经添加到BeanPostProcessor的list当中

这是监听器的BeanPostProcessor。

3.8判断是否有这些和环境变量相关的Bean。如果没有,那就给你添加bean到BeanFactory

包含系统环境变量、JVM环境变量、监控的对象。

3.4postProcessBeanFactory

这是一个模板方法

3.5.invokeBeanFactoryPostProcessors(内容很多,后面再讲)

扫描类,生成BeanDefinition,然后将BeanDefinition放到BeanFactory中

在执行这个方法之前,只是生成了BeanFactory容器自己需要用到的BeanDefinition,但是用户定义的类的BeanDefinition还没有生成,比如userService和orderService。

3.6.registerBeanPostProcessors

将扫描到的BeanPostProcessors实例化并排序,并添加到BeanFactory的beanPostProcessors属性中去,在Bean创建的时候会用beanPostProcessors。

3.7.initMessageSource

国际化

如果我们定义了messageSource名字的Bean,在这里就会将它设置为项目的国际化,否则使用spring默认的国际化工具。

3.8.initApplicationEventMulticaster

注册事件发布器,进行事件的发布。

如果程序员定义了那就用定义的,否则就用默认生成的发布器SimpleApplicationEventMulticaster

3.9.onRefresh

模板方法

3.10.registerListeners

注册监听器,将程序员定义好的监听器存储起来,设置到发布器的属性中去。

3.11.finishBeanFactoryInitialization,完成bean工厂的初始化!

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		// 如果BeanFactory中存在名字叫conversionService的Bean,则设置为BeanFactory的conversionService属性
		// ConversionService是用来进行类型转化的
		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));
		}

		// Register a default embedded value resolver if no BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		// 设置默认的占位符解析器  ${xxx}  ---key
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		// 实例化非懒加载的单例Bean
		beanFactory.preInstantiateSingletons();
	}

3.11.1ConversionService

设置一些类型转换器的Bean

3.11.2设置默认的占位符解析器,${XXX},解析Environment的key-value

3.11.3 preInstantiateSingletons,实例化非懒加载的单例Bean,bean生命周期的入口!!!重点!!后面会详细讲!

3.12.finishRefresh

3.12.1initLifecycleProcessor();

和Spring容器的生命周期有关。我们可以实现smartLiftcycle接口,然后重写start,stop,running方法,检测Spring容器的生命周期。

3.12.2publishEvent

发布 容器启动完成的事件

4.invokeBeanFactoryPostProcessors

作用:生成BeanDefinition,将BeanDefinition注册到bean工厂中,其中包括相关配置类、userService(程序员自己定义的)等全部定义的bean。

核心方法是invokeBeanFactoryPostProcessors,其中一个入参为List<BeanFactoryPostProcessor> beanFactoryPostProcessors,它主要包含两个部分:BeanFactoryPostProcessor(后执行)和BeanDefinitionRegistryPostProcessor(先执行)(可以注册新的beanDefinition)

postProcessBeanDefinitionRegistry:可以注册新的beanDefinition,创建beanDefinition;

postProcessBeanFactory:只能修改beanDefinition,增强beanDefinition;

postProcessBeanDefinitionRegistry继承postProcessBeanFactory!

1.1先执行通过ApplicationContext.add添加进来的BeanDefinitionRegistryPostProcessor 的

postProcessBeanDefinitionRegistry()方法。

这个方法中有个重要的方法processConfigBeanDefinitions,它会解析定义的配置类,生成所有BeanDefinition

// beanFactoryPostProcessors集合一般情况下 都是空的,除非我们手动调用容器的addBeanFactoryPostProcessor方法添加了
			// beanFactoryPostProcessors中可能包含了:普通BeanFactoryPostProcessor对象和BeanDefinitionRegistryPostProcessor对象
			// 对于BeanDefinitionRegistryPostProcessor对象,会执行自己的postProcessBeanDefinitionRegistry()方法
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);// 先执行postProcessBeanDefinitionRegistry方法
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

1.2 getBeanNamesForType

拿到的类型是BeanDefinitionRegistryPostProcessor

先将拿到的ConfigurationClassPostProcessor(配置类的PostProcessor)加入list

1.3核心:然后按顺序,顺序为实现了PriorityOrdered接口、Ordered接口、自定义的PostProcessor的postProcessBeanDefinitionRegistry()方法。(按顺序去将实现了PriorityOrdered、Ordered接口的类,生成BeanDefinition

1.4核心:然后开始执行postProcessBeanFactory,也是按顺序执行,依次执行子接口的方法、实现了PriorityOrdered接口、Ordered接口、自定义的PostProcessor的postProcessBeanFactory()方法。(增强BeanDefinition,修改属性

使用:我们可以自定义实现BeanFactoryPostProcessor接口或者它的子类BeanDefinitionRegistryPostProcessor,重写他们的方法。子类可以新增BeanDefinition,父类可以增强或者修改BeanDefinition的一些属性

5.registerBeanPostProcessors

作用:将扫描到的BeanPostProcessors实例化并排序,添加到BeanFactory的beanPostProcessors属性中去。(添加BeanPostProcessor到BeanPostProcessors中,创建bean的时候使用它)

循环、排序、加到beanPostProcessors的list中!

1.getBeanNamesForType

首先,拿到BeanPostProcessors类型的Bean(也就是拿到所有的BeanPostProcessor)

2.分类

根据实现的接口类型,进行分类。(PriorityOrdered、Ordered、其他)

3.排序

根据实现的接口类型,进行排序。(PriorityOrdered、Ordered、其他)

4.添加到list当中(其中实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor放到list的最后面,意思可能是用户定义的先放(用户的优先级较高),然后存放容器提供的)

list指的是存放BeanPostProcessor(后置处理器)的集合,在创建Bean的时候,会经常用到这个list。

private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();


http://www.kler.cn/a/289387.html

相关文章:

  • D67【python 接口自动化学习】- python基础之数据库
  • 设计模式-七个基本原则之一-迪米特法则 + 案例
  • [SWPUCTF 2022 新生赛]Power! 反序列化详细题解
  • vue3+vite搭建脚手架项目本地运行electron桌面应用
  • 云计算:定义、类型及对企业的影响
  • 【在Linux世界中追寻伟大的One Piece】多路转接epoll
  • 常用性能参数检查方法图示
  • Unity ScriptableObject持久化操作
  • 装饰器模式及应用【理论+代码】
  • 弱通联条件下的人机混合控制
  • 蓝桥杯备赛day02:递推
  • 【Linux操作系统】:Linux生产者消费者模型
  • 数据分析-MAC 编程环境安装教程
  • 淘客APP的前后端分离架构设计
  • 学习记录——day42 多态
  • 算法图解(2)
  • 【Day08】
  • weak_ptr是否有计数方式,在哪分配的空间。
  • MacBook Pro M3 安装 Node.js v14 的兼容性
  • 进阶SpringBoot之 Shiro(6)整合 Thymeleaf
  • 【word导出带图片】使用docxtemplater导出word,通知书形式的word
  • 0基础学习爬虫系列:Python环境搭建
  • Anaconda的环境管理操作命令详解-学习篇
  • mysql创建数据库和表
  • list的简单实现
  • springblade-JWT认证缺陷漏洞CVE-2021-44910