SpringBoot源码解析:创建SpringApplication对象实例
上篇文章SpringBoot自动装配原理解析中,我们分析了SpringBoot的自动装配原理以及
@SpringBootApplication
注解的原理,本篇文章则继续基于上篇文章中的main方法来分析SpringApplication
这个类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
点击run
方法一路跟踪下来,发现首先做的是实例化SpringApplication
对象实例
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
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 = deduceWebApplicationType();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
- 首先看一下
deduceWebApplicationType
方法
private WebApplicationType deduceWebApplicationType() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null)) {
return WebApplicationType.REACTIVE;
}
for (String className : "javax.servlet.Servlet", org.springframework.web.context.ConfigurableWebApplicationContext") {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
}
大抵意思就是根据当前项目中是否存在上方的几个类来推断出当前的web环境,这里因为SpringBoot默认使用的web框架是SpringMVC,所以最后返回结果为WebApplicationType.SERVLET
- 加载所有的
ApplicationContextInitializer
和ApplicationListener
的实现类
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
可以看到主要还是用的SpringFactoriesLoader
这个类去加载这两个接口的实现类,加载到类以后使用反射的方式构造出这些类的实例,然后根据这些实现类上的Order
注解的值进行排序
关于这些实现类的具体作用请关注后续的文章
- 最后一行的意义是找到入口方法main所在的类,赋值给全局变量
mainApplicationClass
SpringBoot源码解析:创建SpringApplication对象实例的更多相关文章
- springboot源码解析 - 构建SpringApplication
1 package com.microservice.framework; 2 3 import org.springframework.boot.SpringApplication; 4 impor ...
- 【附3】springboot源码解析 - 构建SpringApplication
package com.microservice.framework; import org.springframework.boot.SpringApplication; import org.sp ...
- 附3 springboot源码解析 - 构建SpringApplication
package com.microservice.framework; import org.springframework.boot.SpringApplication; import org.sp ...
- SpringBoot源码解析系列文章汇总
相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的SpringBoot源码解析系列文章的汇总,当你使用SpringBoot不仅仅满足于基本使用时.或者出去面试被面试官虐了时.或者说想要深入了解一下 ...
- springboot源码解析-管中窥豹系列之Initializer(四)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- springboot源码解析-管中窥豹系列之自动装配(九)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- springboot源码解析-管中窥豹系列之总体结构(一)
一.简介 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- springboot源码解析-管中窥豹系列之项目类型(二)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
随机推荐
- 关于微信开发者工具创建项目和导入项目半天不响应或者socket hang out
笔者的电脑系统是macOS Catalina(10.15),其实之前的系统版本也遇到一样的问题,网络环境是学校实验室. 解决办法:连接手机Wi-Fi 原理:目前不清楚,清楚的小伙伴可在下方留言交流
- 201871010134-周英杰《面想对象程序设计(java)》第十一周学习总结
项目 内容 <面向对象程序设计(java)> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/ ...
- nginx 常见的问题
1.server匹配优先级 nginx 读取文件名是按照文件排序优先读取的顺序 对与一样的server 优先使用先读取到的 2.location匹配优先级 = 进行普通字符精确匹配,也就是 ...
- 怎么安装python3
解压 这个压缩包 2.把解压后的python文件夹所在的路径配置到环境变量 3.鼠标移动到计算机上---右键---属性----高级系统设置---环境变量,打开如下界面 4.在系统变量里选择pa ...
- Mysql基础知识--概述和索引
一.Mysql概述 MySQL原来隶属于MySQL公司,总部位于瑞典 2008.1.16MySQL被SUN公司收购 2009年SUN公司被Oracle公司收购 常见的软件版本 GA(general A ...
- python中使用rsa加密
前提不多说, 为什么使用RSA加密请自行搜索,直接正为: 一. 生成公钥及私钥, 并保存 二. 使用公钥加密, 私钥解密 后记: 通常使用中, 会先对数据进行bas64加密, 再对加密后的内容使用rs ...
- tornado请求与响应
tornado中处理请求与响应的类如下, 所有视图类必须继承该类: tornado.web.RequestHandler 一. 响应之self.write()方法 1. 该方法可返回值的类型: 当返 ...
- 洛谷p3384【模板】树链剖分题解
洛谷p3384 [模板]树链剖分错误记录 首先感谢\(lfd\)在课上调了出来\(Orz\) \(1\).以后少写全局变量 \(2\).线段树递归的时候最好把左右区间一起传 \(3\).写\(dfs\ ...
- 获取本地连接ip地址(通用版)
@echo off & setlocal enabledelayedexpansionrem 如果系统中有route命令,优先采用方案1:for /f "tokens=3,4&quo ...
- Manjaro Linux安装后第一件事
环境:Manjaro KDE 使用中科大源 USTC Mirror 当然也可以勾选所有中国镜像源 谷歌加上云pinyin拼音输入法,不亚于搜狗 fcitx-qt5 kcm-fcitx (confi ...