SpringBoot源码分析
一:简介
- 由Pivotal团队提供的全新框架
- 其设计目的是用来简化新Spring应用的初始搭建以及开发过程
- 使用了特定的方式来进行配置
- 快速应用开发领域
二:运行原理以及特点
运行原理:
SpringBoot为我们做的自动配置,确实方便快捷,今天来了解一下它的原理:
特点:
- 可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
- 内嵌Tomcat或Jetty等Servlet容器;
- 提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
- 尽可能自动配置Spring容器;
- 提供准备好的特性,如指标、健康检查和外部化配置;
- 绝对没有代码生成,不需要XML配置。
三:重点了解
- 约定优于配置
- 开箱即用
- 程序和注解
1:约定优于配置
90%以上的项目呢,配置都差不多,所以呢spring团队,就搞出了一个通用的配置,以后我们程序猿就不需要再去配置这些繁杂的配置了. 如果用的ssm,所有的maven依赖,版本,都需要我们程序猿去控制,去找依赖,并且互相配合依赖.依赖没有配合好,jar冲突,,出了问题就需要程序猿去解决,一般非常耗时的.
补充:约定优于配置也被称为习惯优于配置、约定大于配置
提示:全局配置名称,必须是 application 这是spring规定好的,别的识别不了
配置文件生效顺序:properties > yml > yaml
2:开箱即用
说明:
1:内嵌Tomcat或Jetty等Servlet容器;
2:用来简化新Spring应用的初始搭建以及开发过程
3:每一个stater都是一个场景功能
<!--引入web starter启动器 常见的场景--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
3:注解和程序
/*表明此类是springboot启动类,服务类
@SpringBootApplication是一个复合注解
包括@ComponentScan,和@SpringBootConfiguration,@EnableAutoConfiguration*/
@SpringBootApplication
public class Demo100Application {//main 程序的入口public static void main(String[] args) {/*SpringApplicationrun*/SpringApplication.run(Demo100Application.class, args);}
}
3.1:注解:
3.1.0:总述:
1:@ComponentScan: 该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 <context:component-scan>
2:@EnableAutoConfiguration 这个注解它所加的组件―就是我们在 pom 中申明的组件﹐以及springBoot默认提供给我用的组件 将组建实例化,交由ioc容器去管理2.1:@AutoConfigurationPackage :自动配置包2.2:@Import({AutoConfigurationImportSelector.class}):载入selector,识别AutoConfigutaion类并import
3:@SpringBootConfiguration3.1:@Configuration3.2:@Component解释:@SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类,
并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名
3.1.1:配置类注解:
@SpringBootConfiguration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> </bean>
</beans>
@Configuration
public class Config {@Beanpublic Map createMap(){Map map = new HashMap();map.put("username","gxz");map.put("age",27);return map;}
}
@Component
public class test {
}
3.1.2:核心注解
@EnableAutoConfiguration:是我们的核心注解旳开启白动配置/自动装配
@Import({AutoConfigurationImportSelector.class}):(核心中的核心)!!!
@AutoConfigurationPackage :自动配置包 @Import({AutoConfigurationImportSelector.class}):载入selector,识别AutoConfigutaion类并import
- 1
- 2
- 3
3.1.3:扫描包注解
@ComponentScan: 该注解默认会扫描该类所在的包下所有的配置类,相当于之前的 context:component-scan
@ComponentScan
提示:Properties中所有的配置 其实 底层都对应了 一个类的属性
3.2:程序:
3.2.1:实例化SpringApplication
SpringApplication初始化时主要做三件事情:
1.根据classpath下是否存在(ConfigurableWebApplicationContext)判断是否要启动一个web applicationContext
2.SpringFactoriesInstances加载classpath下所有可用的ApplicationContextInitializer
3.SpringFactoriesInstances加载classpath下所有可用的ApplicationListener
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//1.根据classpath下是否存在(ConfigurableWebApplicationContext)判断是否要启动一个web applicationContextthis.webApplicationType = WebApplicationType.deduceFromClasspath();//2.SpringFactoriesInstances加载classpath下所有可用的ApplicationContextInitializersetInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//3.SpringFactoriesInstances加载classpath下所有可用的ApplicationListenersetListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();
}
3.2.2:实例化完成后调用run()方法
调用run()方法执行的过程主要分为以下几步:
1.遍历SpringApplication初始化过程中加载的SpringApplicationRunListeners
2.调用Starting()监听SpringApplication的启动
3.加载SpringBoot配置环境(ConfigurableEnvironment)
4.设置banner属性
5.创建ConfigurableApplicationContext(应用配置上下文)
6.将listeners、environment、applicationArguments、bannner等重要组件与上下文对象关联
7.bean的实力化完成
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();//1.遍历SpringApplication初始化过程中加载的SpringApplicationRunListenersSpringApplicationRunListeners listeners = getRunListeners(args);//2.调用starting()监听SpringApplication的启动listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//3.加载SpringBoot配置环境ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);configureIgnoreBeanInfo(environment);//4.设置banner属性Banner printedBanner = printBanner(environment);//5.创建ConfigurableApplicationContext(应用配置上下文)context = createApplicationContext();exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//6.将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联prepareContext(context, environment, listeners, applicationArguments, printedBanner);//7.实例化beanrefreshContext(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;
}
3.2.2.1:遍历SpringApplication初始化过程中加载的SpringApplicationRunListeners
private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger,getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
3.2.2.2:调用Starting()监听SpringApplication的启动
public void starting() {//遍历所有的SpringApplicationRunListener,调用starting()方法监听SpringApplication的启动for (SpringApplicationRunListener listener : this.listeners) {listener.starting();}
}
3.2.2.3:加载SpringBoot配置环境(ConfigurableEnvironment)
加载SpringBoot配置环境(configurableEnvironment),如果是通过web容器发布,会加载StandardEnvironment。将配置文件(Environment)加入到监听器对象中(SpringApplicationRunListeners)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environment//如果environment不为空直接返回 || 如果是web环境则直接实例化StandardServletEnvironment类 || 如果不是web环境则直接实例化StandardEnvironment类ConfigurableEnvironment environment = getOrCreateEnvironment();//配置环境信息configureEnvironment(environment, applicationArguments.getSourceArgs());//通知所有的监听者,环境已经准备好了listeners.environmentPrepared(environment);bindToSpringApplication(environment);if (!this.isCustomEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,deduceEnvironmentClass());}ConfigurationPropertySources.attach(environment);return environment;
}
3.2.2.4:设置banner属性
private Banner printBanner(ConfigurableEnvironment environment) {//如果未开启banner打印直接返回if (this.bannerMode == Banner.Mode.OFF) {return null;}//创建ResourceLoader对象ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader: new DefaultResourceLoader(getClassLoader());//创建SpringApplicationBannerPrinter,该对象用来打印bannerSpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);//如果bannerMode模式为LOG,则将bannner打印到log文件中if (this.bannerMode == Mode.LOG) {return bannerPrinter.print(environment, this.mainApplicationClass, logger);}//打印banner到控制台return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
3.2.2.5:初始化ConfigurableApplicationContext(应用配置上下文)SpringApplicationRunListeners
在SpringBoot中,应用类型分为三类
public enum WebApplicationType {/*** The application should not run as a web application and should not start an* embedded web server.*/// 应用程序不是web应用,也不应该用web服务器去启动NONE,/*** The application should run as a servlet-based web application and should start an* embedded servlet web server.*///应用程序应作为基于servlet的web应用程序运行,并应启动嵌入式servlet web(tomcat)服务器SERVLET,/*** The application should run as a reactive web application and should start an* embedded reactive web server.*///应用程序应作为 reactive web应用程序运行,并应启动嵌入式 reactive web服务器。REACTIVE;
}
根据webEnvironment是否是web环境创建默认的contextClass,AnnotationConfigEnbeddedWebApplicationContext(通过扫描所有注解类来加载bean)和ConfigurableWebApplicationContext),最后通过BeanUtils实例化上下文对象,并返回。
protected ConfigurableApplicationContext createApplicationContext() {//根据webEnvironment是否是web环境创建默认的contextClassClass<?> contextClass = this.applicationContextClass;if (contextClass == null) {try {switch (this.webApplicationType) {case SERVLET://AnnotationConfigServletWebServerApplicationContextcontextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);break;case REACTIVE://AnnotationConfigReactiveWebServerApplicationContextcontextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);break;default://AnnotationConfigApplicationContextcontextClass = Class.forName(DEFAULT_CONTEXT_CLASS);}}catch (ClassNotFoundException ex) {throw new IllegalStateException("Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",ex);}}//BeanUtils实例化上下文对象return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
3.2.2.6:将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {//设置上下文的environmentcontext.setEnvironment(environment);//应用上下文后处理postProcessApplicationContext(context);//在context refresh之前,对其应用ApplicationContextInitializerapplyInitializers(context);//上下文准备listeners.contextPrepared(context);//打印启动日志和启动应用的profileif (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beansConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//向beanFactory注册单例bean:命令行参数beanbeanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {//向beanFactory注册单例bean:banner beanbeanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// Load the sources//获取SpringApplication的primarySources属性Set<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//将bean加载到应用上下文load(context, sources.toArray(new Object[0]));//向上下文添加ApplicationListener,并广播ApplicationPreparedEvent事件listeners.contextLoaded(context);
}
3.2.2.7:bean的实例化完成,刷新应用上下文
相关文章:

SpringBoot源码分析
一:简介 由Pivotal团队提供的全新框架其设计目的是用来简化新Spring应用的初始搭建以及开发过程使用了特定的方式来进行配置快速应用开发领域 二:运行原理以及特点 运行原理: SpringBoot为我们做的自动配置,确实方便快捷&#…...

约数个数和约数之和算法总结
知识概览 约数个数 基于算数基本定理,假设N分解质因数的结果为 可得对于N的任何一个约数d,有 因为N的每一个约数和~的一种选法是一一对应的,根据乘法原理可得, 一个数的约数个数为 约数之和 一个数的约数之和公式为 多项式乘积的…...

数据结构-怀化学院期末题(322)
图的深度优先搜索 题目描述: 图的深度优先搜索类似于树的先根遍历,是树的先根遍历的推广。即从某个结点开始,先访问该结点,然后深度访问该结点的第一棵子树,依次为第二顶子树。如此进行下去,直到所有的结点…...

小手也能用的高性能鼠标,自定义空间还挺高,雷柏VT9Pro mini上手
今年搭载PAW3395传感器的电竞鼠标很受欢迎,雷柏就出了不少型号,满足各种喜好的玩家选择,像是近期新出的搭载3395高定版的VT9Pro和VT9Pro mini,就在轻量化的基础上,满足了各种手型的玩家的使用需要,而且价格…...

CDN加速原理详解
一、CDN加速是什么意思 CDN是Content Delivery Network)英文首字母的缩写,中文翻译为内容分发网络,由于CDN是为加快网络访问速度而被优化的网络覆盖层,因此被形象地称为”网络加速器”,即CDN加速。CDN加速是通过将网站…...
sqlachemy orm create or delete table
sqlacehmy one to one ------detial to descript 关于uselist的使用。如果你使用orm直接创建表关系,实际上在数据库中是可以创建成多对多的关系,如果加上uselistFalse 你会发现你的orm只能查询出来一个,如果不要这个参数orm查询的就是多个,一对多的…...

科普小米手机、华为手机、红米手机、oppo手机、vivo手机、荣耀手机、一加手机、realme手机如何设置充电提示音
用空空鱼就可以设置,上面还有很多提示音素材还可以设置满电和低电提醒...

zookeeper应用场景之分布式的ID生成器
1. 分布式ID生成器的使用场景 在分布式系统中,分布式ID生成器的使用场景非常之多: 大量的数据记录,需要分布式ID。大量的系统消息,需要分布式ID。大量的请求日志,如restful的操作记录,需要唯一标识&#x…...

Java--Spring项目生成雪花算法数字(Twitter SnowFlake)
文章目录 前言步骤查看结果 前言 分布式系统常需要全局唯一的数字作为id,且该id要求有序,twitter的SnowFlake解决了这种需求,生成了符合条件的这种数字,本文将提供一个接口获取雪花算法数字。以下为代码。 步骤 SnowFlakeUtils …...

紫光展锐M6780丨画质增强——更炫的视觉体验
智能显示被认为是推动数字化转型和创新的重要技术之一。研究机构数据显示,预计到2035年底,全球智能显示市场规模将达到1368.6亿美元,2023-2035年符合年增长率为36.4%。 随着消费者对高品质视觉体验的需求不断增加,智能手机、平板…...

控制el-table的列显示隐藏
控制el-table的列显示隐藏,一般的话可以通过循环来实现,但是假如业务及页面比较复杂的话,list数组循环并不好用。 在我们的页面中el-table-column是固定的,因为现在是对现有的进行维护和迭代更新。 对需要控制列显示隐藏的页面进…...
2024上海国际冶金及材料分析测试仪器设备展览会
2024上海国际冶金及材料分析测试仪器设备展览会 时间:2024年12月18~20日 地点:上海新国际博览中心 ◆ 》》》组织机构: 主办单位:全联冶金商会、中国宝武钢铁集团有限公司、上海市金属学会 支持单位ÿ…...

商业定位,1元平价商业咨询:豪威尔咨询!平价咨询。
在做生意之前,就需要对企业整体进行一完整的商业定位,才能让商业定位带动企业进行飞速发展。 所以,包含商业定位的有效工作内容就显得极为重要,今天,小编特地为大家整理出了商业定位所需要的筹备的工作,如下…...

2. Presto应用
该笔记来源于网络,仅用于搜索学习,不保证所有内容正确。文章目录 1、Presto安装使用2、事件分析3、漏斗分析4、漏斗分析UDAF开发开发UDF插件开发UDAF插件 5、漏斗测试 1、Presto安装使用 参考官方文档:https://prestodb.io/docs/current/ P…...

工业级安卓PDA超高频读写器手持掌上电脑,RFID电子标签读写器
掌上电脑,又称为PDA。工业级PDA的特点就是坚固,耐用,可以用在很多环境比较恶劣的地方。 随着技术的不断发展,加快了数字化发展趋势,RFID技术就是RFID射频识别及技术,作为一种新兴的非接触式的自动识别技术&…...

Prompt提示工程上手指南:基础原理及实践(一)
想象一下,你在装饰房间。你可以选择一套标准的家具,这是快捷且方便的方式,但可能无法完全符合你的个人风格或需求。另一方面,你也可以选择定制家具,选择特定的颜色、材料和设计,以确保每件家具都符合你的喜…...
Redis如何保证缓存和数据库一致性?
背景 现在我们在面向增删改查开发时,数据库数据量大时或者对响应要求较快,我们就需要用到Redis来拿取数据。 Redis:是一种高性能的内存数据库,它将数据以键值对的形式存储在内存中,具有读写速度快、支持多种数据类型…...

学完C/C++,再学Python是一种什么体验?
你好,我是安然无虞。 文章目录 变量及类型变量类型动态类型特性 注释输入输出通过控制台输出通过控制台输入 运算符算术运算符关系运算符逻辑运算符赋值运算符 条件循环语句条件语句语法格式代码案例缩进和代码块空语句pass 循环语句while循环语法格式代码案例 for…...

ssm基于Java的壁纸网站设计与实现论文
目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…...
零基础也可以探索 PyTorch 中的上采样与下采样技术
目录 torch.nn子模块Vision Layers详解 nn.PixelShuffle 用法与用途 使用技巧 注意事项 参数 示例代码 nn.PixelUnshuffle 用法与用途 使用技巧 注意事项 参数 示例代码 nn.Upsample 用法与用途 使用技巧 注意事项 参数 示例代码 nn.UpsamplingNearest2d …...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...