当前位置:   article > 正文

SpringBoot源码分析2_springboot源码实现

springboot源码实现

序言

本人为初学者,对SpringBoot源码的理解尚浅,若笔记有误,欢迎各位读者指正;

本人参考了大佬的文章 SpringBoot2 | SpringBoot启动流程源码分析(一) ,其中对启动流程步骤进行了七步划分,觉得划分得挺好,后续的文章也是会依此进行展开;

上节回顾

通过debug,在尚未深入逻辑代码时,可以了解到SpringBoot简单的启动流程:
1、框架启动运行的时候,会先启动一个时间监控器,监控器可以记录总任务及各个任务的运行时间; => stopWatch.start();
2、接着初始化并启动监听器 => listeners.starting();
3、配置好Context的运行环境 => prepareContext(context, environment, listeners, applicationArguments, printedBanner);
4、读取配置文件 => refreshContext();
5、加载Bean到bean工厂中 => afterRefresh(context, applicationArguments);

启动流程的划分

一、进入run方法
public ConfigurableApplicationContext run(String... args) {
		//时间监控
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//java.awt.headless是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true,系统变量默认为true
		configureHeadlessProperty();
		//获取spring.factories中的监听器变量,args为指定的参数数组,默认为当前类SpringApplication
		//第一步:获取并启动监听器
		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();
			//第四步:实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
			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 {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

SpringBoot 启动流程划分的七步分别是:
1、获取并启动监听器
2、构造容器环境
3、创建容器
4、实例化SpringBootExceptionReporter.class
5、准备容器
6、刷新容器
7、刷新容器后的拓展接口

二、进入StopWatch类

概述
这个类相对来说还是比较容易看懂的;
这是一个计时模块,目的为了记录applicationq启动所耗时间,并用于在日志打印中进行输出,日志打印信息如下图所示;
日志打印信息
代码不难理解,在此便不加赘述;

三、第一步 | 监听器

概述
开启监听器的作用:

1)获取监听器

【1】进入run方法

	SpringApplicationRunListeners listeners = getRunListeners(args);
	listeners.starting();
  • 1
  • 2

首先通过 debug, 得到监听器为EventPublishingRunListener, 其中listeners包含11个监听器:
在这里插入图片描述

【2】进入getRunListeners方法

接着,寻找监听器实例化的代码

	//SpringApplication class
	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}
	
	//SpringApplication class 
	//进入getSpringFactoriesInstances,在此类中对EventPublishingRunListener进行实例化;
	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); // names.size = 1; names = {EventPublishingRunListener}
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); // instances.size = 1;
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

	//springApplication class 
	//进入createSpringFactoriesInstances类 创建工厂类的实例化对象
	//整个springboot 获取 factories的方式统一如下:
	private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
			ClassLoader classLoader, Object[] args, Set<String> names) {
		List<T> instances = new ArrayList<>(names.size());
		for (String name : names) {
			try {
				//通过类对象的getDeclaredConstructor方法获得构造器对象
				//装载class文件到内存
				Class<?> instanceClass = ClassUtils.forName(name, classLoader);
				Assert.isAssignable(type, instanceClass);
				Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
				//调用工具类的instantiateClass方法,使用给定的构造函数实例化类
				//主要通过反射创建实例
				T instance = (T) BeanUtils.instantiateClass(constructor, args);
				instances.add(instance);
			}
			catch (Throwable ex) {
				throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
			}
		}
		return instances;
	}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

监听器的逻辑处理过程是这样的,SpringFactoriesLoader.loadFactoryNames(type, classLoader))先获得监听器 EventPublishingRunListening 的名字,然后通过instanceClass.getDeclaredConstructor 方法获得构造器对象,最后调用工具类的instantiateClass方法,利用构造器对象实例化监听器类;

2)开启监听器

listeners.starting();
开启监听器会进入EventPublishingRunListener 类的starting方法,

	//EventPublishingRunListener class
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}


	//SimpleApplicationEventMulticaster class
	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

	//利用给定的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);
		}
	}
	
	//
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			//利用监听器处理要响应的事件
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isTraceEnabled()) {
					logger.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/125595
推荐阅读
相关标签
  

闽ICP备14008679号