文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Boot 监听器详解

2023-09-27 13:12

关注

Spring Boot 3.x系列文章

  1. Spring Boot 2.7.8 中文参考指南(一)
  2. Spring Boot 2.7.8 中文参考指南(二)-Web
  3. Spring Boot 源码阅读初始化环境搭建
  4. Spring Boot 框架整体启动流程详解
  5. Spring Boot 系统初始化器详解
  6. Spring Boot 监听器详解

监听器的介绍

通过前面的几篇文章,我们都能看到SpringApplicationRunListener,SpringApplicationRunListener 是SpringApplication 的运行监听器,提供Spring Boot启动时各个运行状态的监听,可以在应用程序启动的时候执行一些自定义操作或记录一些信息。SpringApplicationRunListener 在run中加载SpringApplicationRunListeners listeners = getRunListeners(args);
ApplicationListener是Spring 提供的上下文监听器,可用于监听指定感兴趣的事件。

监听器的使用

SpringApplicationRunListener

SpringApplicationRunListener 的使用比较简单,实现该接口,并在META-INF/spring.factories中定义该实现

MyApplicationRunListener.java

public class MyApplicationRunListener implements SpringApplicationRunListener {    @Override    public void starting(ConfigurableBootstrapContext bootstrapContext) {        System.out.println("Application 启动");    }    @Override    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {        System.out.println("环境已准备完毕");    }    @Override    public void contextPrepared(ConfigurableApplicationContext context) {        System.out.println("在创建和准备ApplicationContext之后,但在加载源之前调用");    }    @Override    public void contextLoaded(ConfigurableApplicationContext context) {        System.out.println("上下文准备完毕,未刷新");    }    @Override    public void started(ConfigurableApplicationContext context, Duration timeTaken) {        System.out.println("上下文已刷新,应用程序已启动,但尚未调用CommandLineRunners和ApplicationRunners");    }    @Override    public void ready(ConfigurableApplicationContext context, Duration timeTaken) {        System.out.println("在刷新应用程序上下文并且调用了所有CommandLineRunner和ApplicationRunner之后,在运行方法完成之前立即调用");    }    @Override    public void failed(ConfigurableApplicationContext context, Throwable exception) {        System.out.println("当运行应用程序时发生故障时调用");    }}

META-INF/spring.factories

org.springframework.boot.SpringApplicationRunListener=com.springboot.demo.listeners.MyApplicationRunListener

运行情况:
在这里插入图片描述

ApplicationListener

1、实现ApplicationListener接口

MyApplicationListener.java

@Slf4jpublic class MyApplicationListener implements ApplicationListener<ApplicationStartedEvent> {    @Override    public void onApplicationEvent(ApplicationStartedEvent event) {        log.info("应用启动完成");    }}

META-INF/spring.factories

org.springframework.context.ApplicationListener=com.springboot.demo.listeners.MyApplicationListener

2、addListener

在springApplication 中添加,同样达到效果

SpringApplication springApplication = new SpringApplication(SpringBootDemoApplication.class);springApplication.addListeners(new MyApplicationListener());

3、context.istener.classes

在配置文件中添加该配置,value为MyApplicationListener的全路径限定名

context:  listener:    classes: com.springboot.demo.listeners.MyApplicationListener

4、@EventListener

该注解是spring 提供的方式,支持同时监听多种事件,支持SpEL表达式

@Component@Slf4jpublic class MyApplicationListener2 {    //监听单个事件    @EventListener    public void listenerApplicationStarted(ApplicationStartedEvent event) {        log.info("应用启动完成");    }        @EventListener({ApplicationEnvironmentPreparedEvent.class})    public void listenerApplicationEnv() {        //实际测试,没有监听到,后面说明原理        log.info("监听到了环境准备完成事件");    }        //监听多个事件    @EventListener({ApplicationReadyEvent.class, ApplicationStartedEvent.class})    public void listenerApplication() {        log.info("监听到了多个事件");    }    //自己发布了一个Person事件,Person并没有继承ApplicationEvent    @EventListener    public void myCustomListener(Person person) {        log.info("监听到自己发布的事件,{}", person);    }    //只有Person事件中name属性值为csdn时才接收到    @EventListener(condition = "#person.name == 'csdn'")    public void myCustomListener2(Person person) {        log.info("SpEL表达式监听到自己发布的事件,{}", person);    }}

原理解析

SpringApplicationRunListener 的原理在之前的文章都有体现,可以查看《Spring Boot 框架整体启动流程详解》,我们只需要关注ApplicationListener。

Spring Boot 中不同的使用方式有不同的加载,我们一个个来分析。

1、从spring.factories中加载

首先Spring Boot 会在SpringApplication初始化的时候从META-INF/spring.factories中加载ApplicationListener的实现,并保存在private List> listeners;中,待后续使用。
在这里插入图片描述

第二个关键是EventPublishingRunListener,在run方法中通过SpringApplicationRunListeners listeners = getRunListeners(args);加载,getRunListeners 从 spring.factories加载SpringApplicationRunListener的实现保存在SpringApplicationRunListeners内部,其相当于是代理器,Spring Boot 内部只定义了一个EventPublishingRunListener实现。
在这里插入图片描述
在Spring Boot 中在不同的阶段调用不同的SpringApplicationRunListeners方法,如图只是部分
在这里插入图片描述
starting为例,会在SpringApplicationRunListeners内部通过循环前期加载的SpringApplicationRunListener实现,此处只需要关注EventPublishingRunListener
在这里插入图片描述
进入EventPublishingRunListenerstarting方法中,starting调用同类的multicastInitialEvent,事件定义为ApplicationStartingEvent

private void multicastInitialEvent(ApplicationEvent event) {refreshApplicationListeners();this.initialMulticaster.multicastEvent(event);}

refreshApplicationListeners 会从SpringApplication保存的listeners中读取初始化时加载的ApplicationListener实现,并添加到SimpleApplicationEventMulticaster的内部类DefaultListenerRetriever中,待后续使用。

private void refreshApplicationListeners() {this.application.getListeners().forEach(this.initialMulticaster::addApplicationListener);}

第三个关键是SimpleApplicationEventMulticasterthis.initialMulticaster.multicastEvent(event) 调用到了SimpleApplicationEventMulticaster中,multicastEvent又调用了一个同名方法。

public void multicastEvent(ApplicationEvent event) {multicastEvent(event, null);}@Overridepublic void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {//获取事件类的类型信息ResolvableType type = (eventType != null ? eventType : ResolvableType.forInstance(event));// 获取执行事件的线程池,如果设置了,可以异步执行Executor executor = getTaskExecutor();//获取指定事件类型的监听器集合for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {//如果定义了执行线程池,则用线程池调用if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {//同步调用监听器invokeListener(listener, event);}}}protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {//获取失败处理器ErrorHandler errorHandler = getErrorHandler();if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}}@SuppressWarnings({"rawtypes", "unchecked"})private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {//此处执行事件监听器的onApplicationEvent方法listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||(event instanceof PayloadApplicationEvent payloadEvent &&matchesClassCastMessage(msg, payloadEvent.getPayload().getClass()))) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception.Log loggerToUse = this.lazyLogger;if (loggerToUse == null) {loggerToUse = LogFactory.getLog(getClass());this.lazyLogger = loggerToUse;}if (loggerToUse.isTraceEnabled()) {loggerToUse.trace("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

实际上到这里流程已经走完了,最后listener.onApplicationEvent(event);调用到自定义的MyApplicationListener中。

对于如何获取指定事件类型的监听器集合,getApplicationListeners(event, type),代码比较复杂,可看也可不看。

getApplicationListeners 方法在SimpleApplicationEventMulticaster 的父类AbstractApplicationEventMulticaster中,传入传播的事件类bean和事件的类型信息。

protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {//获取事件发生的对象Object source = event.getSource();Class<?> sourceType = (source != null ? source.getClass() : null);//根据事件的类型信息和源对象组成一个监听器的缓存keyListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);// 创建一个新的监听器检索缓存CachedListenerRetriever newRetriever = null;// 根据key从检索缓存中获取缓存的监听器封装类CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey);//如果不存在if (existingRetriever == null) {//判断事件类型和源对象能否用指定的classLoader加载// 创建并缓存一个新的ListenerRetrieverif (this.beanClassLoader == null ||(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {newRetriever = new CachedListenerRetriever();//如果指定键没有关联值,则存入新值,返回null,有关联值返回关联值existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever);//有关联值,就不填充新值,将创建的对象取消关联if (existingRetriever != null) {newRetriever = null;  }}}//缓存检索器中有值,就返回缓存的事件监听器列表if (existingRetriever != null) {Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();if (result != null) {return result;}}//缓存检索器中没有值的话,继续检索return retrieveApplicationListeners(eventType, sourceType, newRetriever);}
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {List<ApplicationListener<?>> allListeners = new ArrayList<>();Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);Set<ApplicationListener<?>> listeners;Set<String> listenerBeans;//从默认检索器中读取监听器列表和监听器bean名称synchronized (this.defaultRetriever) {listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);}// 循环添加已经注册的监听器,包括ApplicationListenerDetector加载的监听器for (ApplicationListener<?> listener : listeners) {//检查指定的监听器是否是需要关注的事件if (supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {filteredListeners.add(listener);}allListeners.add(listener);}}// 通过bean名称来添加监听器,可能与上面的方式重叠,但这里会有一些新的元数据if (!listenerBeans.isEmpty()) {//获取bean工厂ConfigurableBeanFactory beanFactory = getBeanFactory();for (String listenerBeanName : listenerBeans) {try {//判断指定的监听器bean是否是需要关注的事件if (supportsEvent(beanFactory, listenerBeanName, eventType)) {//获取监听器beanApplicationListener<?> listener =beanFactory.getBean(listenerBeanName, ApplicationListener.class);//最终判断if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {if (beanFactory.isSingleton(listenerBeanName)) {filteredListeners.add(listener);}else {filteredListenerBeans.add(listenerBeanName);}}allListeners.add(listener);}}else {// 移除不支持的监听器Object listener = beanFactory.getSingleton(listenerBeanName);if (retriever != null) {filteredListeners.remove(listener);}allListeners.remove(listener);}}catch (NoSuchBeanDefinitionException ex) {}}}//排序AnnotationAwareOrderComparator.sort(allListeners);if (retriever != null) {if (filteredListenerBeans.isEmpty()) {retriever.applicationListeners = new LinkedHashSet<>(allListeners);retriever.applicationListenerBeans = filteredListenerBeans;}else {retriever.applicationListeners = filteredListeners;retriever.applicationListenerBeans = filteredListenerBeans;}}return allListeners;}

看下最终判断的部分:supportsEvent(listener, eventType, sourceType)

protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener gal ? gal :new GenericApplicationListenerAdapter(listener));//通过判断给定的事件类型是否与要关注的事件类型一致,并且支持给定的源类型return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));}

这里会将监听器包装成GenericApplicationListenerAdapter,在构造器中解析出监听器关注的事件类型信息。

public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {Assert.notNull(delegate, "Delegate listener must not be null");this.delegate = (ApplicationListener<ApplicationEvent>) delegate;//解析出事件类型信息this.declaredEventType = resolveDeclaredEventType(this.delegate);}
public boolean supportsEventType(ResolvableType eventType) {//如果是GenericApplicationListener 的实现,它扩展了SmartApplicationListenerif (this.delegate instanceof GenericApplicationListener gal) {return gal.supportsEventType(eventType);}//如果是SmartApplicationListener的实现else if (this.delegate instanceof SmartApplicationListener sal) {Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();return (eventClass != null && sal.supportsEventType(eventClass));}else {//其他类型判断return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));}}@Overridepublic boolean supportsSourceType(@Nullable Class<?> sourceType) {return (!(this.delegate instanceof SmartApplicationListener sal) || sal.supportsSourceType(sourceType));}

2、addListener

由于addListener是在run方法执行之前就添加到了SpringApplication中,所以加载原理同第一种方式相同

3、context.listener.classes

该配置的监听器,由Spring Boot 内置的DelegatingApplicationListener处理,该监听器定义在Spring Boot Jar包的META-INF/spring.factories中。

public void onApplicationEvent(ApplicationEvent event) {//环境准备完毕if (event instanceof ApplicationEnvironmentPreparedEvent preparedEvent) {//从context.listener.classes加载配置的事件监听器List<ApplicationListener<ApplicationEvent>> delegates = getListeners(preparedEvent.getEnvironment());if (delegates.isEmpty()) {return;}//新创建一个SimpleApplicationEventMulticaster,跟以前用的不是同一个this.multicaster = new SimpleApplicationEventMulticaster();for (ApplicationListener<ApplicationEvent> listener : delegates) {this.multicaster.addApplicationListener(listener);}}if (this.multicaster != null) {//监听到其他事件的时候向所有注册在该广播器上的监听器广播事件this.multicaster.multicastEvent(event);}}

this.multicaster.multicastEvent(event);后面的逻辑与前面的相同

4、@EventListener

在之前的实例中,我们监听了一个ApplicationEnvironmentPreparedEvent事件,但实际测试却没有监听到,因为@EventListener要在SpringApplication.run的refreshContext中才会被加载,而ApplicationEnvironmentPreparedEvent事件发生在refreshContext之前。
@EventListener 是Spring 提供的注解,在EventListenerMethodProcessor中被加载,并包装成ApplicationListener实例。

Spring Boot 的refreshContext 最终会调用到Spring 的AbstractApplicationContext refresh()

EventListenerMethodProcessor是一个BeanFactoryPostProcessor,会在refresh 的invokeBeanFactoryPostProcessors(beanFactory) 中进行调用

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {//使用注册委托类处理BeanFactoryPostProcessor的实现PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}

getBeanFactoryPostProcessors()会获取已经加载的BeanFactoryPostProcessor实现,比如准备上下文中的PropertySourceOrderingBeanFactoryPostProcessor。
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors内部的方法很长

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {Set<String> processedBeans = new HashSet<>();//首先处理是BeanDefinitionRegistry的实例if (beanFactory instanceof BeanDefinitionRegistry registry) {List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {regularPostProcessors.add(postProcessor);}}// 然后其中分别处理实现了 PriorityOrdered、Ordered 和其余的处理器List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();//处理实现了PriorityOrdered的处理器String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// 处理实现了Ordered的处理器postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// 最后是剩下的处理器boolean reiterate = true;while (reiterate) {reiterate = false;postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);reiterate = true;}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();}// 调用迄今为止处理的所有处理器的postProcessBeanFactory回调invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// 其他情况调用在上下文实例中注册的工厂处理程序invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}// 处理 BeanFactoryPostProcessor 实现的实例String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);//在实现PriorityOrdered、Ordered和其他的BeanFactoryPostProcessors之间分离List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {if (processedBeans.contains(ppName)) {// 跳过-已在上面的第一阶段中处理}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// 首先,调用实现PriorityOrdered的BeanFactoryPostProcessorssortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);//调用实现Ordered的BeanFactoryPostProcessorsList<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 最后调用其他的BeanFactoryPostProcessorsList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}//EventListenerMethodProcessor会在此处被调用invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);//清除缓存的合并bean定义,因为后处理程序可能已经修改了原始元数据,例如替换值中的占位符。。。beanFactory.clearMetadataCache();}
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {//步骤记录器StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process").tag("postProcessor", postProcessor::toString);//循环调用postProcessBeanFactorypostProcessor.postProcessBeanFactory(beanFactory);postProcessBeanFactory.end();}}

EventListenerMethodProcessor类中:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {this.beanFactory = beanFactory;//获取EventListenerFactory实现类,其用于处理EventListener注解,//将其封装成ApplicationListenerMap<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);List<EventListenerFactory> factories = new ArrayList<>(beans.values());AnnotationAwareOrderComparator.sort(factories);this.eventListenerFactories = factories;}

EventListenerMethodProcessor 实现了SmartInitializingSingleton接口,会在refresh中的finishBeanFactoryInitialization(beanFactory)处调用,finishBeanFactoryInitialization 的作用是实例化所有剩余的非惰性单例。

DefaultListableBeanFactory类中:

//预实例化所有非懒加载的单例 bean,并触发所有适用 bean 的初始化后回调。public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// 访问 beanDefinitionNames,以允许初始化方法注册新的 bean 定义的列表的副本List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 触发所有非延迟加载的单例 bean 的实例化for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//如果是工厂 bean,检查是否需要实例化if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {getBean(beanName);}}//如果不是工厂bean,则实例化 beanelse {getBean(beanName);}}}// 触发所有适用bean的初始化后回调for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {// 启动一个 smart-initialize 的 StartupStep 作为性能分析;       // 在执行完 smartSingleton.afterSingletonsInstantiated() 之后结束这个 StartupStep。StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);smartSingleton.afterSingletonsInstantiated();smartInitialize.end();}}}

通过smartSingleton.afterSingletonsInstantiated()又执行到了EventListenerMethodProcessorafterSingletonsInstantiated,后面又是一长串,我们直接看最后的重点吧。
在这里插入图片描述
首先根据@EventListener创建成ApplicationListener,然后通过addApplicationListener将监听器存入上下文中,后面的逻辑跟前面是相同的。

内置的监听器

Spring Boot 内置了不少监听器,每个监听器都有自己的作用
在这里插入图片描述

内置的事件

Spring Boot 包中部分事件:
BootstrapContextClosedEvent、ExitCodeEvent、AvailabilityChangeEvent、ParentContextAvailableEvent、ApplicationContextInitializedEventApplicationEnvironmentPreparedEventApplicationFailedEventApplicationPreparedEventApplicationReadyEventApplicationStartedEventApplicationStartingEventWebServerInitializedEvent、ReactiveWebServerInitializedEvent、ServletWebServerInitializedEvent

Spring 包中部分事件:
ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ServletRequestHandledEvent

总结

最后还是用一张图来总结整个流程

在这里插入图片描述


作者其他文章:
Prometheus 系列文章

  1. Prometheus 的介绍和安装
  2. 直观感受PromQL及其数据类型
  3. PromQL之选择器和运算符
  4. PromQL之函数
  5. Prometheus 告警机制介绍及命令解读
  6. Prometheus 告警模块配置深度解析
  7. Prometheus 配置身份认证
  8. Prometheus 动态拉取监控服务
  9. Prometheus 监控云Mysql和自建Mysql

Grafana 系列文章,版本:OOS v9.3.1

  1. Grafana 的介绍和安装
  2. Grafana监控大屏配置参数介绍(一)
  3. Grafana监控大屏配置参数介绍(二)
  4. Grafana监控大屏可视化图表
  5. Grafana 查询数据和转换数据
  6. Grafana 告警模块介绍
  7. Grafana 告警接入飞书通知

Spring Boot Admin 系列

  1. Spring Boot Admin 参考指南
  2. SpringBoot Admin服务离线、不显示健康信息的问题
  3. Spring Boot Admin2 @EnableAdminServer的加载
  4. Spring Boot Admin2 AdminServerAutoConfiguration详解
  5. Spring Boot Admin2 实例状态监控详解
  6. Spring Boot Admin2 自定义JVM监控通知
  7. Spring Boot Admin2 自定义异常监控
  8. Spring Boot Admin 监控指标接入Grafana可视化

来源地址:https://blog.csdn.net/weixin_40972073/article/details/131073017

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯