springboot(2.4.1)源代码分析五refreshContext

  |   0 评论   |   0 浏览

上一篇记录了springboot的应用上下文的初始化、准备以及加载,本篇接着记录run 方法中最核心的方法,refreshContext,刷新上下文,这里有初始化bean工厂,单例对象实例化等等逻辑,算是spring启动过程中关键一步,涉及的方法和逻辑也很多,下面还是先看run方法。

public ConfigurableApplicationContext run(String... args) {
		long startTime = System.nanoTime();
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context); //这么一个重要的方法,取名叫刷新上下文,容易让人忽视,实际上这个方法很关键
			afterRefresh(context, applicationArguments);
			......
		return context;
	}

refreshContext方法中最核心的逻辑就在org.springframework.context.support.AbstractApplicationContext.refresh()这个方法中:

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

			//准备刷新工作
			prepareRefresh();

			//获取 BeanFactory 实例。其中包含 读取 bean 配置,创建bean 实例对象相关代码逻辑。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			//对获取的 BeanFactory  实例对象进行预处理
			prepareBeanFactory(beanFactory);

			try {
				//子类重写此方法进行定制化处理.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// 回调 BeanFactoryPostProcessors 实现类的postProcessBeanFactory方法,进行BeanFactory后置处理。
				invokeBeanFactoryPostProcessors(beanFactory);

				// 向 BeanFactory 中注册 BeanPostProcessor 实现类
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				//设置 context 消息的国际化实现类。如果没有配置,则使用 DelegatingMessageSource 实现。
				initMessageSource();

				//设置 context 广播器(applicationEventMulticaster)。如果没有配置,则使用 SimpleApplicationEventMulticaster 实现。
				initApplicationEventMulticaster();

				// 根据需要,子类自定义 onRefresh()
				onRefresh();

				//  注册 Listeners (列表),广播 earlyApplicationEvents 事件.
				registerListeners();

				// BeanFactory 最终的初始化操作.
				finishBeanFactoryInitialization(beanFactory);

				// 上下文(context) 后续处理逻辑.
				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 {
				// 清理公共缓存。
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

重点方法说明:

  • prepareRefresh

刷新方法之前预处理上下文信息:

  1. 记录服务启动是时间戳
  2. 设置当前服务 context 关闭标记(closed),活动标记(active)
  3. 根据需要执行特殊的属性初始化操作。
  4. 校验必须配置属性是否设置成功
  5. 设置早期的事件监听列表 ApplicationListener 列表。
  • prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)

对获取的 BeanFactory 实例对象进行预处理。

  1. 设置 Bean 的类加载器(beanClassLoader)。
  2. 根据配置 spring.spel.ignore 添加表达式解析工具类实例(StandardBeanExpressionResolver)。
  3. 添加属性编辑器注册器(ResourceEditorRegistrar)。
  4. 添加 Aware 接口执行器(ApplicationContextAwareProcessor),并将 Aware的子接口 接口设置为忽略依赖接口。
  5. 注册 指定类型类的实例。BeanFactory.class, beanFactory
  6. 添加实现BeanPostProcessor接口的 Listener 装饰器 (ApplicationListenerDetector)。后续将实现 ApplicationListener 的bena添加到 applicationListeners 列表钟。
  7. 如果配置了loadTimeWeaver实现,则添加实现BeanPostProcessor接口的 LoadTimeWeaverAwareProcessor。后续给实现LoadTimeWeaverAware 的bean设置LoadTimeWeaver实现对象。实际中使用较少。
    类加载期织入(LTW) : 在类加载器加载时,通过字节码编辑技术将切面织入目标类字节码上 。(https://www.jianshu.com/p/25cd25046fab)
    类加载期织入有两种方式:一种是在 main 方法执行之前,通过 premain 来实现;另一种是在程序运行中,通过 attach api 来实现。
    运行期织入:在创建类对象实例时,使用CGLib代理或JDK动态代理进行切面的织入。
    
  8. 将环境变量和系统属性相关的对象实例注册到 单例Bean Map中。
    getEnvironment().getSystemProperties() JVM 启动时相关的环境属性信息
    getEnvironment().getSystemEnvironment() OS 系统的环境变量相关属性信
  • invokeBeanFactoryPostProcessors(beanFactory)

回调 BeanFactoryPostProcessors 实现类的postProcessBeanFactory方法,进行BeanFactory后置处理。

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()

  1. 根据 PriorityOrdered,Ordered以及常规的 BeanDefinitionRegistryPostProcessor 实现类 顺序依次调用 的 postProcessBeanDefinitionRegistry 方法。
  2. 根据 PriorityOrdered,Ordered以及常规的 BeanFactoryPostProcessors 实现类 顺序依次调用 的postProcessBeanFactory方法。
  • registerBeanPostProcessors(beanFactory)

向 BeanFactory 中注册 BeanPostProcessor 实现类。

PostProcessorRegistrationDelegate.registerBeanPostProcessors
1.从 BeanFactory 取出 beanDefinitionMap 中所有 BeanPostProcessor 实现类
2. 按 PriorityOrdered,Ordered以及nonOrdered 顺序添加到 BeanFactory的beanPostProcessors 列表中。
如果 一个实现类继承 MergedBeanDefinitionPostProcessor 接口时,则添加到列表最后。

  • registerListeners()

    注册 Listeners (列表),广播 earlyApplicationEvents 事件。
    1.将 context 的 applicationListeners (列表) 添加到广播器(applicationEventMulticaster)的applicationListeners(列表)中。
    2.将 BeanFactory 中管理的所有 ApplicationListener 类型Bean添加到广播器(applicationEventMulticaster) applicationListenerBeans(列表)中。
    3.将 earlyApplicationEvents 事件列表发送到广播器(applicationEventMulticaster)。将遍历触发满足监听事件的 ApplicationListener.onApplicationEvent 方法。

  • finishBeanFactoryInitialization(beanFactory)

    BeanFactory 最终的初始化操作

    1. beanFactory 设置 ConversionService 实现Bean。
    2. beanFactory 设置 EmbeddedValueResolver 实现Bean。
    3. 获取 beanFactory 所有 LoadTimeWeaverAware 类型 bean。并创建 bean 实例。
    4. beanFactory 设置 tempClassLoader 为 null。阻止再使用 tempClassLoader
    5. beanFactory 冻结配置 beanDefinitionNames。为后面 批量处理单例 Bean 做准备。
    6. beanFactory 获取所有非懒加载的单例 bean对象。
  • finishRefresh()

    上下文(context) 后续处理逻辑。

  1. 清理资源缓存(resourceCaches)信息
  2. 设置 context 的生命周期处理器 (LifecycleProcessor)。如果没有配置,则使用 DefaultLifecycleProcessor 实现。
  3. 调用 LifecycleProcessor.onRefresh 方法。获取 beanFactory 中所有 Lifecycle 类型bean,按 Phased 分组进行排序,然后遍历执行 Lifecycle.start 方法。
  4. 发布 ContextRefreshedEvent 事件。先向当前上下文(context) 环境发送事件广播。然后向父类发布 ContextRefreshedEvent 事件广播。
  5. 获取 平台 MBeanServer 实现,将 LiveBeansView 和 applicationName 注册到 MBeanServer 中。
  • resetCommonCaches()

清理公共缓存。

1.清理反射中缓存的方法和字段信息。

2.清理注解缓存的信息。

3.清理解析类型相关的缓存信息。

4.清理类加载器相关的信息。

参考:https://www.cnblogs.com/StreamPlume/p/15668476.html


标题:springboot(2.4.1)源代码分析五refreshContext
作者:michael
地址:https://blog.junxworks.cn/articles/2022/12/14/1671010010551.html