聊聊springboot的启动事件

这篇具有很好参考价值的文章主要介绍了聊聊springboot的启动事件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文主要研究一下springboot的启动事件

SpringApplicationEvent

org/springframework/boot/context/event/SpringApplicationEvent.java

public abstract class SpringApplicationEvent extends ApplicationEvent {

	private final String[] args;

	public SpringApplicationEvent(SpringApplication application, String[] args) {
		super(application);
		this.args = args;
	}

	public SpringApplication getSpringApplication() {
		return (SpringApplication) getSource();
	}

	public final String[] getArgs() {
		return this.args;
	}

}

SpringApplicationEvent继承了ApplicationEvent,它有几个子类分表是ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent,期间有异常则抛出ApplicationFailedEvent

SpringApplication.run

org/springframework/boot/SpringApplication.java

	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

SpringApplication的run方法,先触发listeners.starting(),然后执行了prepareEnvironment,之后createApplicationContext,再进行prepareContext和refreshContext,最后触发listeners.started(context),之后执行callRunners,最后触发listeners.running(context),如有异常则会执行handleRunFailure

prepareEnvironment

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		listeners.environmentPrepared(environment);
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

prepareEnvironment会触发listeners.environmentPrepared(environment),即发布ApplicationEnvironmentPreparedEvent

prepareContext

	private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
		context.setEnvironment(environment);
		postProcessApplicationContext(context);
		applyInitializers(context);
		listeners.contextPrepared(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		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());
		}
		// Load the sources
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		load(context, sources.toArray(new Object[0]));
		listeners.contextLoaded(context);
	}

prepareContext会触发listeners.contextPrepared(context),即发布ApplicationContextInitializedEvent,执行完成之后触发listeners.contextLoaded(context),即发布ApplicationPreparedEvent

refreshContext

	private void refreshContext(ConfigurableApplicationContext context) {
		refresh(context);
		if (this.registerShutdownHook) {
			try {
				context.registerShutdownHook();
			}
			catch (AccessControlException ex) {
				// Not allowed in some environments.
			}
		}
	}

	protected void refresh(ApplicationContext applicationContext) {
		Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
		((AbstractApplicationContext) applicationContext).refresh();
	}	

refreshContext会执行refresh方法

org/springframework/context/support/AbstractApplicationContext.java

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				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();
			}
		}
	}

refresh先执行postProcessBeanFactory,比如添加BeanPostProcessors,之后执行invokeBeanFactoryPostProcessors,即执行BeanFactoryPostProcessor的postProcessBeanFactory方法
refresh执行完之后触发listeners.started(context)即发布ApplicationStartedEvent
执行完callRunners之后触发listeners.running(context)即发布ApplicationReadyEvent

handleRunFailure

	private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
			Collection<SpringBootExceptionReporter> exceptionReporters, SpringApplicationRunListeners listeners) {
		try {
			try {
				handleExitCode(context, exception);
				if (listeners != null) {
					listeners.failed(context, exception);
				}
			}
			finally {
				reportFailure(exceptionReporters, exception);
				if (context != null) {
					context.close();
				}
			}
		}
		catch (Exception ex) {
			logger.warn("Unable to close ApplicationContext", ex);
		}
		ReflectionUtils.rethrowRuntimeException(exception);
	}

触发listeners.failed(context, exception)即发布ApplicationFailedEvent

小结

SpringApplication的run方法,先触发listeners.starting()(ApplicationStartingEvent),然后执行了prepareEnvironment(ApplicationEnvironmentPreparedEvent),之后createApplicationContext,再进行prepareContext和refreshContext(ApplicationContextInitializedEvent–>ApplicationPreparedEvent),最后触发listeners.started(context)(ApplicationStartedEvent),之后执行callRunners,最后触发listeners.running(context)(ApplicationReadyEvent),期间有异常会执行handleRunFailure,触发listeners.failed(context, exception)(ApplicationFailedEvent)

其中refresh的时候会执行BeanFactoryPostProcessor的postProcessBeanFactory方法
整体顺序如下:ApplicationStartingEvent --> ApplicationEnvironmentPreparedEvent --> ApplicationContextInitializedEvent --> ApplicationPreparedEvent --> ApplicationStartedEvent --> ApplicationReadyEvent,期间有异常则抛出ApplicationFailedEvent文章来源地址https://www.toymoban.com/news/detail-671415.html

到了这里,关于聊聊springboot的启动事件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring boot 启动报错---java: 无法访问org.springframework.boot.SpringApplication 错误的类文件:

    目录 错误提示信息: 原因: 解决办法: 具体步骤: 主要是因为 spring boot 3.0发布了 ,在创建项目时,默认为3.0 ` 但同时, spring boot 3.0 只支持jdk 17 ,在平时创建时,都喜欢使用jdk8 由于 spring boot 版本默认3.0,同时jdk选择的是 8 ,就会导致这个错误 将 spring boot 版本和jdk统一

    2024年02月15日
    浏览(37)
  • SpringBoot启动报错:java: 无法访问org.springframework.boot.SpringApplication

    报错原因:jdk 1.8版本与SpringBoot 3.1.2版本不匹配 解决方案:将SpringBoot版本降到2系列版本(例如2.5.4)。如下图: 修改版本后切记刷新Meavn依赖 然后重新启动即可成功。如下图:

    2024年02月13日
    浏览(41)
  • 聊聊Spring Boot配置文件:优先级顺序、加载顺序、bootstrap.yml与application.yml区别详解

    在 Spring Boot 中,配置文件的优先级顺序是: application-{profile}.yml ( application-{profile}.properties ) application.yml ( application.properties ) bootstrap.yml ( bootstrap.properties )。其中, {profile} 表示不同的环境配置,如 dev 、 test 、 prod 等。 优先级从高到低,高优先级的配置覆盖低优先级

    2024年01月25日
    浏览(47)
  • Spring Boot——Spring Boot启动原理

    2.1.1Spring Boot入口 2.1.2初始化SpringApplication 准备阶段,在程序运行之前初始化一些属性,用于在后序启动应用程序过程中。 2.1.2.1判断当前应用程序类型 2.1.2.2设置应用程序的所有初始化器(initializers) 上面这段代码主要是通过加载 “spring.factories” 配置文件中指定类型的工厂名

    2024年02月15日
    浏览(35)
  • Spring Boot(四):Spring Boot启动原理分析

    文章目录 Spring Boot启动原理分析 一、依赖导入原理 二、Spring Boot包扫描原理 

    2024年02月01日
    浏览(40)
  • Spring boot 实现监听 Redis key 失效事件

    方式一:修改配置文件 redis.conf 方式二:命令行开启 notify-keyspace-events 选项的默认值为空 notify-keyspace-events 的参数可以是以下字符的 任意组合 , 它指定了服务器该发送哪些类型的通知。 字符 发送的通知 K 键空间通知,所有通知以 keyspace@ 为前缀 E 键事件通知,所有通知以

    2024年02月20日
    浏览(31)
  • Spring Boot 启动流程

    加载配置 Spring Boot在启动时会加载应用程序的配置文件(例如application.properties或application.yml),并将其转化为内部的配置对象。 创建应用程序上下文 Spring Boot会创建一个应用程序上下文(ApplicationContext),它是Spring框架的核心容器。应用程序上下文负责管理Bean的生命周期和

    2024年02月06日
    浏览(35)
  • Spring Boot启动原理

    Spring Boot的自动配置为我们提供了快捷方便的方式来运行Spring应用,但很多开发者对其内部启动原理还不是很明白。这篇博客旨在解开Spring Boot的神秘面纱,帮助大家理解它的启动原理。 我们的Spring Boot应用通常从一个主类开始,这个类包含一个main方法,以及一些注解: @Sp

    2024年02月10日
    浏览(33)
  • 【Spring Boot】Spring Boot自动加载机制:简化应用程序的启动

    在微服务盛行的今天,快速搭建和启动应用程序变得至关重要。Spring Boot作为Java生态系统中主流的框架,其自动加载机制使得开发者能够快速构建和启动应用程序。本文将详细介绍Spring Boot的自动加载机制,并通过代码示例加以说明。 首先,我们要了解Spring Boot自动加载机制

    2024年02月11日
    浏览(27)
  • Spring Boot启动源码分析

    版本:spring-boot-starter-parent版本为2.3.0 Spring Boot项目的启动入口是一个main方法,因此我们从该方法入手即可 跟踪run方法 这里分两步debug: new SpringApplication( primarySources ) 执行run()方法 deduceFromClasspath推断应用程序类型 该方法根据是否存在指定路径的类来推断应用程序类型。有

    2024年02月07日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包