赞
踩
本人为初学者,对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);
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; }
SpringBoot 启动流程划分的七步分别是:
1、获取并启动监听器
2、构造容器环境
3、创建容器
4、实例化SpringBootExceptionReporter.class
5、准备容器
6、刷新容器
7、刷新容器后的拓展接口
概述
这个类相对来说还是比较容易看懂的;
这是一个计时模块,目的为了记录applicationq启动所耗时间,并用于在日志打印中进行输出,日志打印信息如下图所示;
代码不难理解,在此便不加赘述;
概述
开启监听器的作用:
1)获取监听器
【1】进入run方法
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
首先通过 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; }
监听器的逻辑处理过程是这样的,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; } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。