springboot源码解析(二)

内容

上一次分析了SpringApplication的静态run方法是先实例化自己本身,然后再调用实例方法run。实例自己本身已经在上一节中分析完成,本节就分析实例run方法

public ConfigurableApplicationContext run(String... args) {
		//开启并启动计时器
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		//初始化异常报告期集合
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//设置headless属性值到系统中
		configureHeadlessProperty();
		//获取应用程序的监听器组合对象
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//监听器发布应用程序开始启动事件
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			//准备应用上下文环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			//配置忽略的bean信息
			configureIgnoreBeanInfo(environment);
			//打印banner
			Banner printedBanner = printBanner(environment);
			//创建容器
			context = createApplicationContext();
			//获取异常报告器
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//准备容器
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			//刷新容器
			refreshContext(context);
			//刷新容器后处理相关逻辑
			afterRefresh(context, applicationArguments);
			//停止计时器
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			//发布容器启动完成时间
			listeners.started(context);
			//回调容器启动完成后的执行器,执行容器启动完成
			//后要执行的逻辑
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			//发布应用程序running事件
			listeners.running(context);
		}
		catch (Throwable ex) {
			//处理运行异常,主要是通过异常报告器,解析
			//运行时产生的异常,然后解析成容易阅读和
			//方便排查问题的文本,然后打印
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

这个方法执行完,springboot应用程序就执行完成了。当然里面逻辑是很复杂的,不可能是看起来这几行代码这么简单。
首先从宏观整体解释一下这个方法都干了哪些事情,然后逐步进入里面分析。

这里面和主流程密切相关的步骤有以下一些步骤:

1、获得监听器
2、准备应用上下文环境
3、创建和准备容器
4、刷新容器
5、回调容器启动完成后的执行器

后面的章节,我主要对这些步骤进行详细分析。

本节主要分析获得监听器,进入到方法:SpringApplicationRunListeners listeners = getRunListeners(args);中:

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

这个代码是不是很熟悉?
其实就是上节中分析过的从spring.factories文件中获取实现了某一个接口的所有类并实例化后返回实例集合。这里我就不展开分析了。
可能有些同学会有疑问,上一节不是有setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));这个步骤吗,这里的为啥不从上面设置的那个集合中直接拿呢?

其实这里获取的是所有的SpringApplicationRunListener,而上一节中获取的是ApplicationListener,是两个不同的东东。
SpringApplicationRunListeners对象是SpringApplicationRunListener的组合对象,在实例化SpringApplicationRunListeners的时候会把获取到的所有SpringApplicationRunListener对象传入到SpringApplicationRunListeners对象的属性里面。

	SpringApplicationRunListeners(Log log,
			Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = new ArrayList<>(listeners);
	}

这个属性listeners就是所有的SpringApplicationRunListener。
在我们的系统中所有的spring.factories文件中就只有一个SpringApplicationRunListener的实现类,那就是EventPublishingRunListener。

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

这个就是EventPublishingRunListener的构造参数,通反射实例化EventPublishingRunListener的时候就是调用的这个构造函数,执行构造方法的时候初始化了一个initialMulticaster,还把所有的SpringApplication对象里面的所有ApplicationListener对象都注入到了initialMulticaster这个广播器里面。

所以容器在每次发布事件的时候只需要调组合对象SpringApplicationRunListeners的对应方法,进而调用到里面的所有的SpringApplicationRunListener的对应方法,这里只有一个SpringApplicationRunListener就是EventPublishingRunListener;进而调用到所有ApplicationListener的对应方法。

下面我就以容器开始启动这个事件为一个调用链,分析一下:

在这里插入图片描述
进入starting方法

在这里插入图片描述
请看我用红框框起来的地方,接下来进入到下一个调用链
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

总结

SpringApplication对象的实例方法run大概做了以下几件事情:
1、获得监听器
2、准备应用上下文环境
3、创建和准备容器
4、刷新容器
5、回调容器启动完成后的执行器

本节主要解析了获取监听器,监听器是一个组合对象,各个监听器之间的关联关系也进行了分析,大概就是SpringApplicationRunListeners里面包含了多个SpringApplicationRunListener,每个SpringApplicationRunListener里面包含了多个ApplicationListener和一个广播器,用于广播事件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值