1.第一个步骤进入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();//这个type是SERVLET
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//设置初始化
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//设置监听器
this.mainApplicationClass = deduceMainApplicationClass();
}

1.1 看一下 setInitializers 方法做了些什么事情

// type 是 ApplicationContextInitializer.class
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));//返回ApplicationContextInitializer对应的类路径
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);//
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

返回ApplicationContextInitializer对应的类路径

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();//ApplicationContextInitializer
//加载/META-INF/spring.factories下面的文件,并获取ApplicationContextInitializer为key对应的值
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

根据类路径反射生成类的实例

	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 {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
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 setListeners做了什么

//type = ApplicationListener.class  和上面一样获取ApplicationListener的类实例
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));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

1.3 获取主类

private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}

2.第二个步骤调用run方法  

public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();//配置handless参数
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
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 {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}

  2.1 设置系统handless参数

	private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";

private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

  2.2 获取SpringApplicationRunListeners的实例

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

  2.3 准备环境

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();// new StandardServletEnvironment() 创建Servlet环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}

 2.4 console开启banner

图片配置路径:spring.banner.image.location
图片配置名称:banner.{ "gif", "jpg", "png" }
文本配置路径:spring.banner.location
默认数据resource下的:banner.txt

  2.5 创建上下文类

	public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
+ "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";
protected ConfigurableApplicationContext createApplicationContext() {
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

  2.6 准备上下文

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}

  

SpringBoot01-启动类启动做了那些事情的更多相关文章

  1. springBoot项目启动类启动无法访问

    springBoot项目启动类启动无法访问. 网上也查了一些资料,我这里总结.下不来虚的,也不废话. 解决办法: 1.若是maven项目,则找到右边Maven Projects --->Plug ...

  2. springboot 启动类启动跳转到前端网页404问题的两个解决方案

    前段时间研究springboot 发现使用Application类启动的话, 可以进入Controller方法并且返回数据,但是不能跳转到WEB-INF目录下网页, 前置配置 server: port ...

  3. 【spring boot】启动类启动 错误: 找不到或无法加载主类 com.codingapi.tm.TxManagerApplication 的解决方案

    导入的一个外部的spring boot项目,运行启动类,出现错误:找不到或无法加载主类 com.codingapi.tm.TxManagerApplication 解决方案: 将所有错误处理完成后,再 ...

  4. 【spring cloud】子模块module -->导入一个新的spring boot项目作为spring cloud的一个子模块微服务,怎么做/或者 每次导入一个新的spring boot项目,IDEA不识别子module,启动类无法启动/右下角没有蓝色图标

    如题:导入一个新的spring boot项目作为spring cloud的一个子模块微服务,怎么做 或者说每次导入一个新的spring boot项目,IDEA不识别,启动类无法启动,怎么解决 下面分别 ...

  5. asp.net core 系列 2 启动类 Startup.CS

    学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 在探讨Startup启动类之前,我们先来了解下Asp.NET CORE 配置应用程序的执行顺序 ...

  6. 避免在ASP.NET Core 3.0中为启动类注入服务

    本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0类库转换为.NET Core 3.0类库 Part 2 - IHostingE ...

  7. 精尽Spring Boot源码分析 - SpringApplication 启动类的启动过程

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  8. 4.3、Libgdx启动类和配置

    (原文:http://www.libgdx.cn/topic/45/4-3-libgdx%E5%90%AF%E5%8A%A8%E7%B1%BB%E4%B8%8E%E9%85%8D%E7%BD%AE) ...

  9. Spring Boot SpringApplication启动类(二)

    目录 前言 1.起源 2.SpringApplication 运行阶段 2.1 SpringApplicationRunListeners 结构 2.1.1 SpringApplicationRunL ...

  10. Spring Boot SpringApplication启动类(一)

    目录 目录 前言 1.起源 2.SpringApplication 准备阶段 2.1.推断 Web 应用类型 2.2.加载应用上下文初始器 ApplicationContextInitializer ...

随机推荐

  1. java实现第三届蓝桥杯拼音字母

    拼音字母 在很多软件中,输入拼音的首写字母就可以快速定位到某个词条.比如,在铁路售票软件中,输入: "bj"就可以定位到"北京".怎样在自己的软件中实现这个功能 ...

  2. 线性表 & 散列表

    线性表: 数据排成一条线一样的机构,每个线性表上的数据最多只有前后两个方向, 包括 数组,链表,队列,栈. 非线性表 : 数据之间并不是简单的前后关系,有二叉树.图等. 散列表(基于 数组支持按照下标 ...

  3. 掌握SpringBoot-2.3的容器探针:深入篇

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:原创分类汇总及配套源码,涉及Java.Docker.K8S.DevOPS等 关于<Spr ...

  4. bootargs说明 和 下位机静态ip的设置

    setenv bootargs root=/dev/nfs       nfsroot=192.168.1.8:/opt/rootfs      ip=192.168.1.110:192.168.1. ...

  5. 测试-spring源码摘取

    首次加载idea是真的慢... 也许是我电脑性能太差... 我分析他内部有一套索引的机制,需要每次打开现建立... 没有固态的话,首次打开还不如eclipse 第一次使用博客园,以前都在csdn混~ ...

  6. 用turtle画蛇

    import turtle def drawSnake(rad,angle,len,nackrad): for i in range(len): turtle.circle(rad,angle) #画 ...

  7. Arduino控制超声波检测与0.96OLED及串口显示

    Arduino控制超声波检测与0.96OLED及串口显示代码使用库共享(包括超声波检测与U8glib): 使用元件: 0.96寸 12864 I2C OLED 128x64规格 超声波检测模块 湿度模 ...

  8. Rigidbody(刚体)方法的初步学习(一)

    概要:这次将简单的了解Rigidbody中的各种方法属性,以官方的API为顺序研究. 蛮牛API翻译:Rigidbody组件控制物体的位置—它使物体在重力影响下下落,并可计算物体将怎样响应碰撞.当操作 ...

  9. jni 字符串的梳理

    1.实现的功能是java层传递一个字符串到c层2.c层首先将jstring类型转换成char*类型3.c层对字符串进行处理之后,将处理之后的char*类型转换成jstring类型返回给上层的 pack ...

  10. laravel --- composer install之后,项目没有vender目录

    composer install之后,项目没有vender目录 1. 原因一:PHP版本过低 PHP版本需要7.1以上,目前使用的是7.0.23