Spring Boot中的各种事件

spring boot 各种事件贯穿整个启动的生命周期,读懂了这些时间也差不多理解了springboot的启动流程。

SpringApplicationRunListener中的事件

接口org.springframework.boot.SpringApplicationRunListener定义了spring启动过程中各个事件被触发的顶层方法

java 复制代码
public interface SpringApplicationRunListener {
        
        default void starting() {
        }

        
        default void environmentPrepared(ConfigurableEnvironment environment) {
        }
        
        default void contextPrepared(ConfigurableApplicationContext context) {
        }
        
        default void contextLoaded(ConfigurableApplicationContext context) {
        }
        
        default void started(ConfigurableApplicationContext context) {
        }
        
        default void running(ConfigurableApplicationContext context) {
        }
        
        default void failed(ConfigurableApplicationContext context, Throwable exception) {
        }

    }

SpringApplicationRunListener的方法定义很讲究,方法从上到下的顺序也正好是各事件触发的顺序。SpringApplicationRunListener接口的唯一具体实现类是org.springframework.boot.context.event.EventPublishingRunListener

  1. starting接口表示springboot程序准备开始启动,这是最早的事件触发方法,它将触发ApplicationStartingEvent事件。这个事件一般没人关心,目前spring中没有任何逻辑实现依赖于这个事件。
java 复制代码
	//EventPublishingRunListener
	@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}
  1. environmentPrepared接口方法表示Environment对象准备好了,它将触发ApplicationEnvironmentPreparedEvent事件.
java 复制代码
	//EventPublishingRunListener
	@Override
	public void environmentPrepared(ConfigurableEnvironment environment) {
		this.initialMulticaster
				.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
	}

不论是本地配置文件还是云端配置中心,它们的配置内容读取都依赖于此事件。

ConfigFileApplicationListener本地配置文件监听器

java 复制代码
public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered{
@Override
	public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
		return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
				|| ApplicationPreparedEvent.class.isAssignableFrom(eventType);
	}

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
		}
		if (event instanceof ApplicationPreparedEvent) {
			onApplicationPreparedEvent(event);
		}
	}
}

BootstrapApplicationListener云端配置中心监听器

java 复制代码
public class BootstrapApplicationListener
		implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
		
}
  1. contextPrepared表示ApplicationContext实例化后,所有的ApplicationContextInitializer实例的initialize已经被依次调用执行完毕。
    这个方法将触发ApplicationContextInitializedEvent事件
java 复制代码
	//EventPublishingRunListener
	@Override
	public void contextPrepared(ConfigurableApplicationContext context) {
		this.initialMulticaster
				.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
	}
  1. contextLoaded 方法表示ApplicationContext的各种资源已经被读取加载完毕(主要是各种BeanDefination的读取),但还没有进行上下文刷新。此方法将触发ApplicationPreparedEvent事件
java 复制代码
	//EventPublishingRunListener
	@Override
	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));
	}
  1. started表示ApplicationContext的refresh刷新完成,但CommandLineRunnersApplicationRunner 这些函数接口还未执行。
java 复制代码
	//EventPublishingRunListener
	@Override
	public void started(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
	}
  1. running方法表示CommandLineRunnersApplicationRunner函数接口也都被调用执行完毕,它是springboot正常启动过程中的最后一个事件,它标志着项目已完全启动,它将触发ApplicationReadyEvent事件。
java 复制代码
	//EventPublishingRunListener
	@Override
	public void running(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
	}
  1. failed表示项目启动过程中出现异常,启动过程中的任意一阶段都可能出错。
java 复制代码
	//EventPublishingRunListener
	@Override
	public void failed(ConfigurableApplicationContext context, Throwable exception) {
		ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
		if (context != null && context.isActive()) {
			// Listeners have been registered to the application context so we should
			// use it at this point if we can
			context.publishEvent(event);
		}
		else {
			// An inactive context may not have a multicaster so we use our multicaster to
			// call all of the context's listeners instead
			if (context instanceof AbstractApplicationContext) {
				for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
						.getApplicationListeners()) {
					this.initialMulticaster.addApplicationListener(listener);
				}
			}
			this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
			this.initialMulticaster.multicastEvent(event);
		}
	}

其他事件

ApplicationContext在刷新完成后,生命周期处理器的默认实现类DefaultLifecycleProcessor的onRefresh方法会被调用,并发布ContextRefreshedEvent事件。
DefaultLifecycleProcessor.onRefresh会调用所有实现SmartLifecycle接口的Spring Bean对象的start方法。

java 复制代码
//DefaultLifecycleProcessor

	@Override
	public void onRefresh() {
		startBeans(true);
		this.running = true;
	}
	private void startBeans(boolean autoStartupOnly) {
		Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
		Map<Integer, LifecycleGroup> phases = new HashMap<>();
		lifecycleBeans.forEach((beanName, bean) -> {
			if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
				int phase = getPhase(bean);
				LifecycleGroup group = phases.get(phase);
				if (group == null) {
					group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
					phases.put(phase, group);
				}
				group.add(beanName, bean);
			}
		});
		if (!phases.isEmpty()) {
			List<Integer> keys = new ArrayList<>(phases.keySet());
			Collections.sort(keys);
			for (Integer key : keys) {
				phases.get(key).start();
			}
		}
	}

WebServerStartStopLifecycle也实现了SmartLifecycle接口,此start方法将启动Tomcat容器,并发布ServletWebServerInitializedEvent事件。

相关推荐
pyniu7 分钟前
项目实站day7--功能之营业额统计,用户数量统计
java·开发语言·spring boot·spring
JIngJaneIL35 分钟前
基于Java旅游信息推荐系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·旅游
JavaBoy_XJ44 分钟前
Kafka在 Spring Boot 项目中的完整配置指南
spring boot·kafka·kafka配置
汝生淮南吾在北1 小时前
SpringBoot+Vue非遗文化宣传网站
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
AI分享猿1 小时前
Java后端实战:SpringBoot接口遇袭后,用轻量WAF兼顾安全与性能
java·spring boot·安全·免费waf·web防火墙推荐·企业网站防护·防止恶意爬虫
清晓粼溪1 小时前
SpringBoot3-02:整合资源
java·开发语言·spring boot
Andy工程师2 小时前
Spring Boot 的核心目标
java·spring boot·后端
vortex52 小时前
【Web开发】从WSGI到Servlet再到Spring Boot
前端·spring boot·servlet
小裕哥略帅2 小时前
Springboot中全局myBaits插件配置
java·spring boot·后端
helloworld工程师3 小时前
Dubbo应用开发之基于Dubbo协议的springboot规范性开发
spring boot·后端·dubbo