1.第一个步骤进入SpringApplication构造函数

  1. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  2. this.resourceLoader = resourceLoader;
  3. Assert.notNull(primarySources, "PrimarySources must not be null");
  4. this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  5. this.webApplicationType = WebApplicationType.deduceFromClasspath();//这个type是SERVLET
  6. setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//设置初始化
  7. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//设置监听器
  8. this.mainApplicationClass = deduceMainApplicationClass();
  9. }

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

  1. // type 是 ApplicationContextInitializer.class
  2. private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
  3. ClassLoader classLoader = getClassLoader();//
  4. // Use names and ensure unique to protect against duplicates
  5. Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));//返回ApplicationContextInitializer对应的类路径
  6. List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);//
  7. AnnotationAwareOrderComparator.sort(instances);
  8. return instances;
  9. }

返回ApplicationContextInitializer对应的类路径

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

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

  1. private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
  2. ClassLoader classLoader, Object[] args, Set<String> names) {
  3. List<T> instances = new ArrayList<>(names.size());
  4. for (String name : names) {
  5. try {
  6. Class<?> instanceClass = ClassUtils.forName(name, classLoader);
  7. Assert.isAssignable(type, instanceClass);
  8. Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
  9. T instance = (T) BeanUtils.instantiateClass(constructor, args);
  10. instances.add(instance);
  11. }
  12. catch (Throwable ex) {
  13. throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
  14. }
  15. }
  16. return instances;
  17. }

1.2 setListeners做了什么

  1. //type = ApplicationListener.class 和上面一样获取ApplicationListener的类实例
  2. private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
  3. ClassLoader classLoader = getClassLoader();
  4. // Use names and ensure unique to protect against duplicates
  5. Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  6. List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
  7. AnnotationAwareOrderComparator.sort(instances);
  8. return instances;
  9. }

1.3 获取主类

  1. private Class<?> deduceMainApplicationClass() {
  2. try {
  3. StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
  4. for (StackTraceElement stackTraceElement : stackTrace) {
  5. if ("main".equals(stackTraceElement.getMethodName())) {
  6. return Class.forName(stackTraceElement.getClassName());
  7. }
  8. }
  9. }
  10. catch (ClassNotFoundException ex) {
  11. // Swallow and continue
  12. }
  13. return null;
  14. }

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

  1. public ConfigurableApplicationContext run(String... args) {
  2. StopWatch stopWatch = new StopWatch();
  3. stopWatch.start();
  4. ConfigurableApplicationContext context = null;
  5. Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
  6. configureHeadlessProperty();//配置handless参数
  7. SpringApplicationRunListeners listeners = getRunListeners(args);
  8. listeners.starting();
  9. try {
  10. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  11. ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
  12. configureIgnoreBeanInfo(environment);
  13. Banner printedBanner = printBanner(environment);
  14. context = createApplicationContext();//
  15. exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
  16. new Class[] { ConfigurableApplicationContext.class }, context);
  17. prepareContext(context, environment, listeners, applicationArguments, printedBanner);
  18. refreshContext(context);
  19. afterRefresh(context, applicationArguments);
  20. stopWatch.stop();
  21. if (this.logStartupInfo) {
  22. new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
  23. }
  24. listeners.started(context);
  25. callRunners(context, applicationArguments);
  26. }
  27. catch (Throwable ex) {
  28. handleRunFailure(context, ex, exceptionReporters, listeners);
  29. throw new IllegalStateException(ex);
  30. }
  31.  
  32. try {
  33. listeners.running(context);
  34. }
  35. catch (Throwable ex) {
  36. handleRunFailure(context, ex, exceptionReporters, null);
  37. throw new IllegalStateException(ex);
  38. }
  39. return context;
  40. }

  2.1 设置系统handless参数

  1. private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
  2.  
  3. private void configureHeadlessProperty() {
  4. System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
  5. System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
  6. }

  2.2 获取SpringApplicationRunListeners的实例

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

  2.3 准备环境

  1. private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
  2. ApplicationArguments applicationArguments) {
  3. // Create and configure the environment
  4. ConfigurableEnvironment environment = getOrCreateEnvironment();// new StandardServletEnvironment() 创建Servlet环境
  5. configureEnvironment(environment, applicationArguments.getSourceArgs());
  6. ConfigurationPropertySources.attach(environment);
  7. listeners.environmentPrepared(environment);
  8. bindToSpringApplication(environment);
  9. if (!this.isCustomEnvironment) {
  10. environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
  11. deduceEnvironmentClass());
  12. }
  13. ConfigurationPropertySources.attach(environment);
  14. return environment;
  15. }

 2.4 console开启banner

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

  2.5 创建上下文类

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

  2.6 准备上下文

  1. private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
  2. SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
  3. context.setEnvironment(environment);
  4. postProcessApplicationContext(context);
  5. applyInitializers(context);
  6. listeners.contextPrepared(context);
  7. if (this.logStartupInfo) {
  8. logStartupInfo(context.getParent() == null);
  9. logStartupProfileInfo(context);
  10. }
  11. // Add boot specific singleton beans
  12. ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  13. beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
  14. if (printedBanner != null) {
  15. beanFactory.registerSingleton("springBootBanner", printedBanner);
  16. }
  17. if (beanFactory instanceof DefaultListableBeanFactory) {
  18. ((DefaultListableBeanFactory) beanFactory)
  19. .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  20. }
  21. if (this.lazyInitialization) {
  22. context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
  23. }
  24. // Load the sources
  25. Set<Object> sources = getAllSources();
  26. Assert.notEmpty(sources, "Sources must not be empty");
  27. load(context, sources.toArray(new Object[0]));
  28. listeners.contextLoaded(context);
  29. }

  

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. STL中的set和multiset

    注意: 1.count() 常用来判断set中某元素是否存在,因为一个键值在set只可能出现0或1次. 2.erase()用法 erase(iterator)  ,删除定位器iterator指向的值 ...

  2. Linux磁盘空间容量不够-通过新增磁盘-挂载原磁盘

    首先上一张图 -------1)首先fdisk 一块磁盘并格式化 mkfs.ext4 /dev/sda15 --------2)将此磁盘挂载在mnt目录下,并将磁盘容量不够的磁盘所有文件进行复制到mn ...

  3. KVM在线扩展虚拟机内存

    环境介绍 在KVM下有一台虚拟机内存不够需要扩展内存.宿主机地址是192.168.1.28.我需要扩展的虚拟机是centos1708vm03. 1.登陆上宿主机查看虚拟机配置 virsh dumpxm ...

  4. springmvc无法进入controller,且报错404

    今天搭建一个springmvc项目时,前台一直报错404,在controller中调试发现程序没有进入controller. 通过多次刷新前台页面,发现第一次进入是会弹出错误提示,第二次之后就直接40 ...

  5. 关于Graph Convolutional Network的初步理解

    为给之后关于图卷积网络的科研做知识积累,这里写一篇关于GCN基本理解的博客.GCN的本质是一个图网络中,特征信息的交互+与传播.这里的图指的不是图片,而是数据结构中的图,图卷积网络的应用非常广泛 ,经 ...

  6. TensorFlow开发者证书 中文手册

    经过一个月的准备,终于通过了TensorFlow的开发者认证,由于官方的中文文档较少,为了方便大家了解这个考试,同时分享自己的备考经验,让大家少踩坑,我整理并制作了这个中文手册,请大家多多指正,有任何 ...

  7. akka-typed(6) - cluster:group router, cluster-load-balancing

    先谈谈akka-typed的router actor.route 分pool router, group router两类.我们先看看pool-router的使用示范: val pool = Rout ...

  8. 君荣一卡通软件mysql转sqlserver 教程

    Mysql数据库转sql数据库方法 注意:新建的SQL数据库一得先登录一次后再做迁移!!!!特别注意 如果客户以前安装的是mysql数据库,现在希望把mysql数据库转换的sql数据库,方法如下: 1 ...

  9. [PyQt5]文件对话框QFileDialog的使用

    概述选取文件夹 QFileDialog.getExistingDirectory()选择文件 QFileDialog.getOpenFileName()选择多个文件 QFileDialog.getOp ...

  10. 小师妹学JVM之:JVM的架构和执行过程

    目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...