Spring Boot 监听器详解

这篇具有很好参考价值的文章主要介绍了Spring 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

运行情况:
Spring Boot 监听器详解

ApplicationListener

1、实现ApplicationListener接口

MyApplicationListener.java

@Slf4j
public 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
@Slf4j
public 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<ApplicationListener<?>> listeners;中,待后续使用。
Spring Boot 监听器详解

第二个关键是EventPublishingRunListener,在run方法中通过SpringApplicationRunListeners listeners = getRunListeners(args);加载,getRunListeners 从 spring.factories加载SpringApplicationRunListener的实现保存在SpringApplicationRunListeners内部,其相当于是代理器,Spring Boot 内部只定义了一个EventPublishingRunListener实现。
Spring Boot 监听器详解
在Spring Boot 中在不同的阶段调用不同的SpringApplicationRunListeners方法,如图只是部分
Spring Boot 监听器详解
starting为例,会在SpringApplicationRunListeners内部通过循环前期加载的SpringApplicationRunListener实现,此处只需要关注EventPublishingRunListener
Spring Boot 监听器详解
进入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);
}

@Override
public 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);
	//根据事件的类型信息和源对象组成一个监听器的缓存key
	ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

	// 创建一个新的监听器检索缓存
	CachedListenerRetriever newRetriever = null;

	// 根据key从检索缓存中获取缓存的监听器封装类
	CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey);
	//如果不存在
	if (existingRetriever == null) {
		//判断事件类型和源对象能否用指定的classLoader加载
		// 创建并缓存一个新的ListenerRetriever
		if (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)) {
				//获取监听器bean
					ApplicationListener<?> 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 的实现,它扩展了SmartApplicationListener
	if (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));
	}
}

@Override
public 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的BeanFactoryPostProcessors
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

	
	//调用实现Ordered的BeanFactoryPostProcessors
	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

	// 最后调用其他的BeanFactoryPostProcessors
	List<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);
				//循环调用postProcessBeanFactory
		postProcessor.postProcessBeanFactory(beanFactory);
		postProcessBeanFactory.end();
	}
}

EventListenerMethodProcessor类中:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	this.beanFactory = beanFactory;

//获取EventListenerFactory实现类,其用于处理EventListener注解,
//将其封装成ApplicationListener
	Map<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,则实例化 bean
			else {
				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,后面又是一长串,我们直接看最后的重点吧。
Spring Boot 监听器详解
首先根据@EventListener创建成ApplicationListener,然后通过addApplicationListener将监听器存入上下文中,后面的逻辑跟前面是相同的。

内置的监听器

Spring Boot 内置了不少监听器,每个监听器都有自己的作用
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、ApplicationContextInitializedEventApplicationEnvironmentPreparedEventApplicationFailedEventApplicationPreparedEventApplicationReadyEventApplicationStartedEventApplicationStartingEventWebServerInitializedEvent、ReactiveWebServerInitializedEvent、ServletWebServerInitializedEvent

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

总结

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

Spring Boot 监听器详解


作者其他文章:
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 系列文章来源地址https://www.toymoban.com/news/detail-475998.html

  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可视化

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

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

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

相关文章

  • Spring中最简单的过滤器和监听器

            Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息

    2024年02月14日
    浏览(42)
  • Spring高手之路15——掌握Spring事件监听器的内部逻辑与实现

    在阅读本文之前需要你已经对事件监听器有了简单的了解,或去阅读前面的文章《 Spring高手之路7——事件机制与监听器的全面探索 》   在 Spring 中, ApplicationContext 可以形成一个层次结构,通常由主容器和多个子容器组成。一个常见的疑问是:当一个事件在其中一个容器

    2024年02月06日
    浏览(48)
  • Spring高手之路7——事件机制与监听器的全面探索

      观察者模式是一种行为设计模式,它定义了对象之间的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。在这个模式中,改变状态的对象被称为主题,依赖的对象被称为观察者。 举个实际的例子: 事件源(Event Source) :可以视

    2024年02月11日
    浏览(43)
  • 【Vue2.x源码系列07】监听器watch原理

    上一章 Vue2计算属性原理,我们介绍了计算属性是如何实现的?计算属性缓存原理?以及洋葱模型是如何应用的? 本章目标 监听器是如何实现的? 监听器选项 - immediate、deep 内部实现 在 Vue初始化实例的过程中,如果用户 options选项中存在侦听器,则初始化侦听器 watch 类型:

    2023年04月20日
    浏览(49)
  • Spring项目配置文件中RabbitMQ监听器各个参数的作用

    spring.rabbitmq.listener.simple.concurrency :设置监听器容器的并发消费者数量,默认为1,即单线程消费。 spring.rabbitmq.listener.simple.max-concurrency :设置监听器容器的最大并发消费者数量。 spring.rabbitmq.listener.simple.prefetch :设置每个消费者从RabbitMQ服务器获取的消息数量,即每次从队列

    2024年02月16日
    浏览(40)
  • 【三十天精通Vue 3】第六天 Vue 3 计算属性和监听器详解

    ✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3

    2024年02月16日
    浏览(41)
  • 【游戏引擎Easy2D】基于基础类型展开的监听器学习详解

       🧛‍♂️ iecne个人主页: 点赞关注收藏评论支持哦~ 💡每天 关注 iecne的作品,一起进步 👉本文收录 专栏 :【C++游戏引擎】 🐳希望大家多多支持🥰一起进步呀! 哈喽大家好,我是 iecne ,本期为大家带来的是CPP/C++【游戏引擎Easy2D】一篇打通引擎顶级类型,Listener。包

    2024年01月17日
    浏览(88)
  • 微信小程序(四)--- 自定义组件详解(properties,数据监听器,纯数据字段,插槽,父子间通信,behaviors)

    目录 一、创建组件 二、引用组件 1、局部引用 2、全局引用 三、组件和页面的区别 四、组件样式隔离 1、注意点 2、修改组件的样式隔离选项  五、数据、方法、属性 1、data数据 2、methods方法 3、properties属性  4、data和properties的区别  5、使用setData修改properties的值  六、数据

    2024年01月24日
    浏览(52)
  • HttpSessionListener监听器和HttpSessionAttributeListener监听器

    1.作用:监听Session创建或销毁,即生命周期监听 2.相关方法: 3.使用场景: 和前面的ServletContextListener等一样,可以用于监控用户上线和离线 4.代码 HttpSessionListener监听器 实现类 HttpSessionAttributeListener监听器 1.作用:监听Session属性的变化,使用少 2.相关方法: 3.代码 监听器 实

    2024年02月04日
    浏览(51)
  • Listener监听器----HttpServletRequest对象的生命周期监听器

    一、HttpServletRequest对象的生命周期监听器         ServletRequestListener接口定义了ServletRequest(是HttpServletRequest接口的父接口类型)对象生命周期的监听行为。 void requestInitialized(ServletRequestEvent sre)         HttpServletRequest对象创建后会触发该监听器方法,并将已创建HttpServletR

    2024年01月23日
    浏览(61)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包