【SpringBoot】SpringBoot 生命周期及相关事件浅析 二

前言

上一章节介绍了 ApplicationStartingEvent ApplicationEnvironmentPreparedEvent生命周期 动作,以及对应 监听器 的行为,本章节继续介绍剩余 事件 相关

版本

SpringBoot 2.3.x

ApplicationContextInitializedEvent


	----------------- prepareContext -----------------

	private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {

		// setEnvironment
		context.setEnvironment(environment);

		// 设置 beanNameGenerator conversionService 等属性
		postProcessApplicationContext(context);

		// 执行所有 ApplicationContextInitializer
		applyInitializers(context);

		// 发布事件 ApplicationContextInitializedEvent
		listeners.contextPrepared(context);
		
		// ...
	}

	------------ EventPublishingRunListener ------------

	public void contextPrepared(ConfigurableApplicationContext context) {
		this.initialMulticaster
				.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
	}
  • 设置 environment 属性
  • 容器 的后处理,包括注册 BeanNameGenerator 单例,设置 resourceLoader 属性、设置 conversionService 属性
  • 依次执行所有 ApplicationContextInitializer#initialize 方法,ApplicationContextInitializer 即构造方法中 自动装配initializers 属性,共有 7
  • 1)DelegatingApplicationContextInitializer:收集所有 environmentcontext.initializer.classes 属性配置的自定义 ApplicationContextInitializer,并执行 initialize 方法,换句话说自定义的 ApplicationContextInitializer 优先级最高
  • 2)SharedMetadataReaderFactoryContextInitializer:注册 CachingMetadataReaderFactoryPostProcessor 后处理器
  • 3)ContextIdApplicationContextInitializer:生成一个 ContextId 类型的 容器标识,并将其注册为 单例
  • 4)ConfigurationWarningsApplicationContextInitializer:注册一个 ConfigurationWarningsPostProcessor 后处理器
  • 5)RSocketPortInfoApplicationContextInitializer:设置 local.rsocket.server.port 属性
  • 6)ServerPortInfoApplicationContextInitializer:设置 local.server.port 等属性
  • 7)ConditionEvaluationReportLoggingListener:设置 ConditionEvaluationReport 属性并注册为 单例
  • 发布 ApplicationContextInitializedEvent

ApplicationContextInitializedEvent 对应的监听器

  • BackgroundPreinitializer:针对 ApplicationContextInitializedEvent 无动作
  • DelegatingApplicationListener:同时发布该事件给所有 自定义监听器

ApplicationPreparedEvent


	----------------- prepareContext -----------------

	private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
		
		// ...

		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();

		/**
		 * 注册对应单例,比如 springApplicationArguments springBootBanner
		 */
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		if (printedBanner != null) {
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
		if (beanFactory instanceof DefaultListableBeanFactory) {
			((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.lazyInitialization) {
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		
		/**
		 * 加载所有资源类
		 */
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		load(context, sources.toArray(new Object[0]));

		/**
		 * 发布事件 ApplicationPreparedEvent
		 */
		listeners.contextLoaded(context);
	}

	------------ EventPublishingRunListener ------------

	public void contextLoaded(ConfigurableApplicationContext context) {
		for (ApplicationListener<?> listener : this.application.getListeners()) {
			if (listener instanceof ApplicationContextAware) {
				((ApplicationContextAware) listener).setApplicationContext(context);
			}
			context.addApplicationListener(listener);
		}
		this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
	}
  • 注册 ApplicationArgumentsBanner 对应的 单例
  • 设置 allowBeanDefinitionOverriding 属性,由 spring.main 属性控制
  • 注册一个 LazyInitializationBeanFactoryPostProcessor 后处理器
  • 加载 资源类,基于 BeanDefinitionLoader 的成员属性 AnnotatedBeanDefinitionReader annotatedReader 加载主类,通常情况下我们的主类作为配置类,后续被 ConfigurationClassPostProcessor 解析
  • 发布 ApplicationPreparedEvent
  • SpringApplication 设置的 监听器容器 绑定起来,同时将 SpringApplication监听器 注册到 容器 中,也就是说这部分监听器也可以监听到 容器 的相关事件

ApplicationPreparedEvent 对应的监听器

  • CloudFoundryVcapEnvironmentPostProcessor:略
  • ConfigFileApplicationListener:注册一个 PropertySourceOrderingPostProcessor 后处理器
  • LoggingApplicationListener:注册几个日志相关的 单例
  • BackgroundPreinitializer:针对 ApplicationPreparedEvent 无动作
  • DelegatingApplicationListener:同时发布该事件给所有 自定义监听器

ApplicationStartedEvent

	// 调用容器的 refresh 方法
	refreshContext(context);

	// 空实现,供拓展
	afterRefresh(context, applicationArguments);
	stopWatch.stop();

	// 打印日志
	if (this.logStartupInfo) {
		new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
	}

	/**
	 * 此处发布 ApplicationStartedEvent
	 */
	listeners.started(context);

	------------ EventPublishingRunListener ------------

	public void started(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
	}
  • 在发布 ApplicationStartedEvent 前,有一个很重要的动作 refreshContext,此处调用了 容器 的 refresh 方法,这是 容器 最核心的方法,配置(刷新) 整个 Spring 容器,单例bean 的注册就是发生在此处
  • 发布 ApplicationStartedEvent 后,容器还会发布了一个 AvailabilityChangeEvent 事件,标识应用状态为 LivenessState.CORRECT

ApplicationStartedEvent 对应的监听器

  • BackgroundPreinitializer:针对 ApplicationStartedEvent 无动作
  • DelegatingApplicationListener:同时发布该事件给所有 自定义监听器

ApplicationReadyEvent

	/**
	 * 此处发布 ApplicationReadyEvent
	 */
	listeners.running(context);

	------------ EventPublishingRunListener ------------
	
	public void running(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
	}
  • 执行完所有 CommandLineRunnerApplicationRunner 后,发布事件 ApplicationReadyEvent
  • 同时容器发布状态为 ReadinessState.ACCEPTING_TRAFFICAvailabilityChangeEvent 事件,表示应用可以正常通信了

ApplicationReadyEvent 对应的监听器

  • BackgroundPreinitializer:在发布 ApplicationEnvironmentPreparedEvent 事件时,此监听器在后台启动一个线程执行 预热 操作,其用到一个 CountDownLatch 使得在 预热 操作执行完成前,所有线程会阻塞在此处。则 ApplicationReadyEvent 事件到达时,如果 预热 完成,预热线程中断

  • DelegatingApplicationListener:同时发布该事件给所有 自定义监听器

ApplicationFailedEvent

应用启动失败,则发布 ApplicationFailedEvent,细节略

总结

  • SpringBoot 抽象出 SpringApplication:Spring应用 的概念,它会根据上下文创建对应的 Environment ApplicationContext
  • Environment ApplicationContext 等都是 Spring 的核心组件,SpringBoot 将其整合到一块,即我们所谓的 约定大于配置
  • ApplicationContext 有它自己的生命周期,在容器的启动过程中,也会发布对应的事件
  • SpringApplication 也有它自己的生命周期,即我们本文介绍的重点
  • 监听器事件 类似于 BeanPostProcessorBean,前者允许我们在合适的时机对 SpringApplication 进行拓展,比如 SpringCloud 的整合,后者允许我们在合适的时机对容器中的 Bean 进行拓展,比如 属性的注入
  • 事件驱动是 SpringBoot 的核心,还是有必要掌握的

参考

不懂SpringApplication生命周期事件?那就等于不会Spring Boot嘛

上一篇:【SpringBoot】SpringBoot 生命周期及相关事件浅析 一

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值