广告
返回顶部
首页 > 资讯 > 后端开发 > JAVA >Spring Boot 监听器详解
  • 805
分享到

Spring Boot 监听器详解

springbootspringjava 2023-09-27 13:09:06 805人浏览 八月长安
摘要

Spring Boot 3.x系列文章 Spring Boot 2.7.8 中文参考指南(一)Spring Boot 2.7.8 中文参考指南(二)-WebSpring Boot 源码阅读初始化

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 内置了不少监听器,每个监听器都有自己的作用
在这里插入图片描述

  • ClearCachesApplicationListener
    应用上下文加载完成后对缓存做清除工作
  • ParentContextCloserApplicationListener
    父应用程序上下文关闭时,会将关闭事件向下传播以关闭该应用程序上下文
  • FileEncodingApplicationListener
    用于监听应用程序环境准备完毕时,如果系统文件编码(spring.mandatory-file-encoding)与环境中配置的值(file.encoding)不匹配时(忽略大小写),会抛出异常,并停止应用程序
  • AnsiOutputApplicationListener
    根据spring.output.ansi.enabled参数配置AnsiOutput
  • DelegatingApplicationListener
    用于委托管理context.listener.classes中配置的监听器
  • LoggingApplicationListener
    配置和初始化Spring Boot 的日志系统
  • EnvironmentPostProcessorApplicationListener
    管理spring.factories文件中注册的EnvironmentPostProcessors

内置的事件

Spring Boot 包中部分事件:
BootstrapContextClosedEvent、ExitCodeEvent、AvailabilityChangeEvent、ParentContextAvailableEvent、ApplicationContextInitializedEventApplicationEnvironmentPreparedEventApplicationFailedEventApplicationPreparedEventApplicationReadyEventApplicationStartedEventApplicationStartingEventWebServerInitializedEventReactiveWEBServerInitializedEvent、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

--结束END--

本文标题: Spring Boot 监听器详解

本文链接: https://www.lsjlt.com/news/419632.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Spring Boot 监听器详解
    Spring Boot 3.x系列文章 Spring Boot 2.7.8 中文参考指南(一)Spring Boot 2.7.8 中文参考指南(二)-WebSpring Boot 源码阅读初始化...
    99+
    2023-09-27
    spring boot spring java
  • 【Spring Boot】Spring—加载监听器
    这里写目录标题 前言加载监听器执行run方法加载配置文件封装Node调用构造器思考 前言 前几天的时候,项目里有一个需求,需要一个开关控制代码中是否执行一段逻辑,于是理所当然的在yml...
    99+
    2023-09-27
    spring boot spring java
  • Spring Boot的listener(监听器)简单使用实例详解
    监听器(Listener)的注册方法和 Servlet 一样,有两种方式:代码注册或者注解注册1.代码注册方式通过代码方式注入过滤器 @Bean public ServletListenerRegistrationBean servlet...
    99+
    2023-05-31
    spring boot listener
  • Spring事件监听详解
    目录一、观察者模式二、spring事件三、注册监听器四、发布事件一、观察者模式 先来看下观察者模式,举个例子 警察和军人是观察者,犯罪嫌疑人是被观察者 代码实现: 定义被观察者接口...
    99+
    2022-11-12
  • Spring boot admin 服务监控利器详解
    目录一、简介二、搭建1、服务端2、客户端3、启动项目4、客户端配置3、微服务3.1、服务端3.2、客户端4、我的微服务预警发送其他服务状态信息思路一、简介 用于对 Spring Bo...
    99+
    2022-11-13
    Spring boot admin 服务监控利器 Spring 服务监控利器
  • Spring事件监听器ApplicationListener源码详解
    目录Spring提供的内置事件:使用方式监听容器的刷新事件自定义事件使用@EventListener监听事件异步发送消息ApplicationListener原理分析发布消息的入口何...
    99+
    2023-05-20
    Spring 事件监听器 Spring ApplicationListener
  • Java Spring 事件监听详情解析
    目录前言需求背景事件概念定义组成事件实现时序图前言 前段时间因为工作的需要用到Spring事件,翻翻文档将功能实现了,但是存在少许理解不畅的地方,今天有空来梳理梳理。 需求背景 叶子...
    99+
    2022-11-13
  • Spring Boot Admin2 实例状态监控详解
    其他相关文章: Spring Boot Admin 参考指南SpringBoot Admin服务离线、不显示健康信息的问题Spring Boot Admin2 @EnableAdminServe...
    99+
    2023-09-16
    spring boot java spring
  • Spring Boot启动事件和监听器的示例分析
    这篇文章将为大家详细讲解有关Spring Boot启动事件和监听器的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Spring Boot 启动事件顺序1、ApplicationStartingEv...
    99+
    2023-06-17
  • Spring MVC 详解 (Spring Boot)
    Spring MVC 详解 - Spring Boot 一、什么是 Spring MVC1.1 MVC 定义1.2 MVC 和 Spring MVC 的关系1.3 学习目的 二、Spring MVC 创建和连接2.1 创建 Sp...
    99+
    2023-12-22
    spring mvc spring boot java 后端
  • 详解spring-boot actuator(监控)配置和使用
    在生产环境中,需要实时或定期监控服务的可用性。spring-boot 的actuator(监控)功能提供了很多监控所需的接口。简单的配置和使用如下:1、引入依赖:<dependency> <groupId>org...
    99+
    2023-05-31
    spring boot actuator
  • 详解Spring事件发布与监听机制
    目录一、ApplicationContext 事件机制二、ApplicationListener 监听器三、ApplicationEvent 事件四、自定义事件和监听器五、注解式监听...
    99+
    2022-11-12
  • Spring的事件和监听器-同步与异步详解
    目录Spring的事件和监听器-同步与异步1、首先新建StartWorkflowEvent.java,2、新建一个监听器StartWorkflowListener.java3、创建一...
    99+
    2022-11-12
  • Spring boot——Actuator 详解
    一、什么是 Actuator Spring Boot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监控和管理Spring Boot 应用。 这个模块是一个采集应用内部信息暴露给外部的模...
    99+
    2023-09-22
    java spring boot
  • Spring Boot Admin的使用详解(Actuator监控接口)
    目录第一部分 Spring Boot Admin 简介admin-server 服务端(admin-server)客户端第二部分 快速入门服务端配置(admin-server)客户端...
    99+
    2022-11-12
  • 深入理解spring boot 监控
    目录一、指标监控二、常用的监控端点 三、定制EndPoint四、spring boot admin(可以使用)一、指标监控 引入jar包: <de...
    99+
    2022-11-12
  • spring boot actuator监控超详细教程
    spring boot actuator介绍 Spring Boot包含许多其他功能,可帮助您在将应用程序推送到生产环境时监视和管理应用程序。 您可以选择使用HTT...
    99+
    2022-11-12
  • Java基础 Servlet监听器详解
    Java基础 Servlet监听器详解 1 概念:Servlet监听器,用来监听web容器的一些对象状态的变化,主要是ServletContext、HttpSession、HttpServletRequestl三类对象状态。Ser...
    99+
    2023-05-31
    java servlet ava
  • SpringBoot详解整合Spring Boot Admin实现监控功能
    目录监控监控的意义可视化监控平台监控原理自定义监控指标监控 ​ 在说监控之前,需要回顾一下软件业的发展史。最早的软件完成一些非常简单的功能,代码不多,错误也少。随着软件功能的逐步完善...
    99+
    2022-11-13
  • Spring实现内置监听器
    目录Spring内置监听器pom.xml文件中加入依赖在web.xml文件中注册监听器获取容器对象1、直接通过key值获取2、通过WebApplicationContextUtils...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作