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事件。

相关推荐
FIN技术铺1 小时前
Spring Boot框架Starter组件整理
java·spring boot·后端
小码的头发丝、2 小时前
Spring Boot 注解
java·spring boot
午觉千万别睡过2 小时前
RuoYI分页不准确问题解决
spring boot
2301_811274312 小时前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
编程重生之路3 小时前
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
java·spring boot·后端
politeboy3 小时前
k8s启动springboot容器的时候,显示找不到application.yml文件
java·spring boot·kubernetes
世间万物皆对象10 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
qq_174482857511 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
代码小鑫13 小时前
A043-基于Spring Boot的秒杀系统设计与实现
java·开发语言·数据库·spring boot·后端·spring·毕业设计
真心喜欢你吖13 小时前
SpringBoot与MongoDB深度整合及应用案例
java·spring boot·后端·mongodb·spring