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 ...
随机推荐
- (九)OpenStack---M版---双节点搭建---Swift(单节点)安装和配置
↓↓↓↓↓↓↓↓视频已上线B站↓↓↓↓↓↓↓↓ >>>>>>传送门 本次搭建仅采用Compute单节点做swift组件 1.Controller安装并配置控制节点 ...
- adb命令之解锁打卡
adb devicesadb shell input keyevent 26 按手机电源键adb shell input swipe 400 1080 40 ...
- 201871010118-唐敬博《面向对象程序设计(java)》第十一周学习总结
在博客园撰写博客(随笔),总结10周学习内容,作业格式要求如下: 博文名称:学号-姓名<面向对象程序设计(java)>第十一周学习总结(1分) 博文正文开头格式:(2分) 项目 内容 这个 ...
- C#基础表达式语句详解(上)
本节内容: 1.表达式的定义: 2.各类表达式概览: 3.语句的定义: 4.语句详解: 1.表达式的定义: 1.1什么是表达式: (定义见下图)各类编程语言对表达式的实现不尽相同,但大体上都符合这个定 ...
- openjdk11 stretch基础镜像无法找到对应openjdk dbg 包的问题
今天在构建一个jdk perf 工具基于openjdk 11 发现8 的dbg 一直可以查找到,但是11的就是没有 参考issue https://github.com/docker-library/ ...
- django -- admin里的配置
前戏 Django给我们提供了一个后台管理系统,方便我们进行数据表的管理 创建超级用户 python manage.py createsuperuser 配置 默认我们登录到后台不显示任何一张表,如果 ...
- 【转】spring的AOP原理,使用场景是什么?
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- [LeetCode] 917. Reverse Only Letters 只翻转字母
Given a string S, return the "reversed" string where all characters that are not a letter ...
- Webpack 一些核心概念了解
Webpack的几个核心概念 Entry:入口,Webpack执行构建的第一步将从Entry开始,可抽象成输入. Module:模块,在Webpack里一切皆模块,一个模块对应一个文件.Webpack ...
- 不同种类的ICP算法
摘自<三维点云数据拼接中ICP及其改进算法综述>