Springboot之事件管家SpringApplicationRunListeners事件管理机制源码分析

本文基于:spring-boot-2.3.12-RELEASE、spring-cloud-Hoxton.SR12(即2.2.9-RELEASE)

Springboot的SpringApplication事件监听是独立于spring容器事件管理的另一套机制,分为:
starting、environmentPrepared、contextPrepared、contextLoaded、started、running、failed等应用阶段的监听

springboot启动的核心方法:
public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		// @A
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			...省略...
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

@A:初步看来,spring-boot使用了 SpringApplicationRunListeners 这个类来抽象了spring应用运行时的一些event;SpringApplicationRunListeners 实则是对SpringApplicationRunListener子类集合的封装

SpringApplication构造方法

在这里插入图片描述

	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		// @A
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		// @B
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

@A、@B:在这里我先讲SpringApplication的构造方法,是因为在构造方法里做了很多事情,跟本文有关的就是框架会在构造方法里从配置文件spring.factories里拿到key为org.springframework.context.ApplicationListener 和 key为org.springframework.context.ApplicationContextInitializer的类,实例化好后缓存起来

这一点很重要,否则后面看代码会很绕;getSpringFactoriesInstances方法源码如下

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		
		// @A
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
       	List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

@A:解析配置文件并实例化,返回对象

SpringApplicationRunListeners 初始化

在调用spring-boot SpringApplication的run方法流程中,有一行代码:SpringApplicationRunListeners listeners = getRunListeners(args);
在这里插入图片描述
getRunListeners方法代码如下:

	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		
		// @A
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        // @B
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

@A:这个方法会到 spring.factories 文件里去拿 org.springframework.boot.SpringApplicationRunListener 为key 的value值
@B:创建对应的实例集合,框架默认为SpringApplicationRunListener提供了一个子类 EventPublishingRunListener,所以instances的size是1

EventPublishingRunListener

我们来看看其构造方法

	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
		// @A
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}

@A:将application里的Listeners加载到自己类中,那么这些Listeners从哪里来的呢?
这就跟上面的 SpringApplication 构造方法有关了,在构造方法里已经将这些listeners提前加载了!(我反正是debug了一大圈才发现!)
这就完成了 EventPublishingRunListener 对象的初始化,后面springapplication的事件体系都由这个类来管控了!

扩展点:spring cloud 就是扩展了 org.springframework.context.ApplicationListener 实现了双容器!下一篇再详细分析一下双容器。

over~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值