springboot是如何工作的

一、前言

现在java后端开发框架比较多的使用springboot框架,springboot是在以前的springMVC进行封装和优化,最大的特点是简化了配置和内置Tomcat。本节通过阅读源码理解springboot是如何工作的。

二、springboot是如何工作的

1、从启动类开始

/**
  *服务启动类
  * @author: 
  * @Description:
  * @Company: 
  * @date: 
  */
@SpringBootApplication(scanBasePackages = {"cn.xxx.common","cn.xxx.admin.*","cn.xxx.interceptor.*"})
@EnableEurekaClient
@EnableApolloConfig
@EnableFeignClients(basePackages = {"cn.xxx.interceptor.*"})
@EnableDiscoveryClient
@MapperScan("cn.xxx.admin.dao")
@EnableSwagger2
@EnableTransactionManagement 
public class BaseAdminApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(BaseAdminApplication.class,args);
	}

}

从代码上可以看出spring通过main方法启动,关键代码是这一句:SpringApplication.run(BaseAdminApplication.class,args);

和注解 @SpringBootApplication(scanBasePackages = {"cn.xxx.common","cn.xxx.admin.*","cn.xxx.interceptor.*"})

通过调用SpringApplication的run方法

	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}

可以看出传入的参数是 类  BaseAdminApplication.class

我们平时的方法很少参数传入一个类,这里传入一个类,就是为了获取这个类的属性,就是它上面的注解之类的

这里就要理解一下java的反射。

接着往下看  run(new Class<?>[] { primarySource }, args);

调用的run方法传入的是 类的数组  Class<?>[] { primarySource },数组中的元素是 BaseAdminApplication.class

继续往下调用

	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

这一段东西又怎么理解?

 new SpringApplication(primarySources).run(args);

这个是构造函数SpringApplication(primarySources),就是初始化出SpringApplication的一个实例对象,它传的值就是 BaseAdminApplication.class ,然后调用run的方法。

先看构成函数里都进行那些初始化

	@SuppressWarnings({ "unchecked", "rawtypes" })
	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();
		this.bootstrapRegistryInitializers = new ArrayList<>(
				getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

这里其实就是封装了配置信息

接下来看看如何运行配置文件和上下文信息

public ConfigurableApplicationContext run(String... args) {
		long startTime = System.nanoTime();
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
			}
			listeners.started(context, timeTakenToStartup);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
			listeners.ready(context, timeTakenToReady);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

这段代码还是很复杂的,因为里面嵌套了很多模块和方法,它表示的就是如何处理配置信息和上下文。

三、扩展,java的反射

Java中的反射机制是指在运行时动态地获取一个类的信息,包括类的方法、属性、构造函数等,而不需要事先知道这个类的具体实现。通过反射机制,可以在程序运行时获取类的信息,并且可以在运行时调用类的方法、创建对象等。

反射机制主要包含以下几个核心类:

一:Class类:表示一个类的类型,可以通过它获取类的构造函数、方法、字段等信息。Class类是反射机制的核心类之一。它代表了一个类的类型,可以用来获取该类的构造函数、方法、字段等信息,也可以用来创建该类的对象。以下是Class类的一些常用方法:

  1. forName(String className):根据类的全限定名获取对应的Class对象。

  2. newInstance():创建该类的一个实例对象。

  3. getConstructor(Class<?>... parameterTypes):获取该类的指定构造函数。

  4. getDeclaredConstructor(Class<?>... parameterTypes):获取该类的指定构造函数,不考虑其访问权限。

  5. getMethod(String name, Class<?>... parameterTypes):获取该类的指定公共方法。

  6. getDeclaredMethod(String name, Class<?>... parameterTypes):获取该类的指定方法,不考虑其访问权限。

  7. getField(String name):获取该类的指定公共字段。

  8. getDeclaredField(String name):获取该类的指定字段,不考虑其访问权限。

在使用反射机制时,通常需要先获取对应的Class对象,然后再通过该对象获取需要的信息或者创建对象。

二:Constructor类:表示一个类的构造函数,可以通过它创建对象。在Java反射机制中,Constructor类表示一个类的构造函数,可以用来创建该类的实例对象。以下是Constructor类的一些常用方法:

  1. newInstance(Object... initargs):使用指定的参数创建该构造函数所表示的类的新实例。

  2. getParameterTypes():获取该构造函数的参数类型。

  3. getModifiers():获取该构造函数的修饰符。

  4. isVarArgs():判断该构造函数是否支持可变参数。

  5. isAccessible():判断该构造函数是否可以被访问。

  6. setAccessible(boolean flag):设置该构造函数的可访问标志。

使用Constructor类可以通过反射机制来创建一个类的实例对象,可以方便地调用私有构造函数等。

三:Method类:表示一个类的方法,可以通过它调用类的方法。Method类是用于表示类或接口的方法的反射机制类。它包含有关方法名称,参数类型,返回类型,访问修饰符等信息的元数据。

使用Method类,可以在运行时动态地调用类的方法,而无需在编译时知道类的确切类型。可以使用以下方法之一获取Method对象:

1.getMethod(String name, Class<?>... parameterTypes):返回具有指定名称和参数类型的公共方法。

2.getDeclaredMethod(String name, Class<?>... parameterTypes):返回具有指定名称和参数类型的方法,无论是否为公共方法。

一旦获得了Method对象,就可以使用invoke()方法调用它来执行方法,需要提供目标对象和方法的参数。如果方法是静态的,则可以将目标对象设置为null。

四:Field类:表示一个类的字段,可以通过它获取和设置类的属性值。Field类代表类或接口的字段,即类或接口中的变量。Field类提供了访问和操作字段的方法,包括获取字段的名称、类型、修饰符、值等。

Field类是通过Java反射机制来实现的,反射机制是一种在运行时分析和操作类、接口、方法、字段等程序构件的机制。使用反射机制,可以在运行时获取一个类的信息,包括其方法、字段、注解、泛型类型等,并可以动态地创建对象、调用方法、访问字段等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/110484.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Proteus仿真】【Arduino单片机】SG90舵机控制

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用SG90舵机等。 主要功能&#xff1a; 系统运行后&#xff0c;舵机开始运行。 二、软件设计 /* 作者&#xff1a;嗨小易&#xff08;QQ&#x…

链表加法与节点交换:数据结构的基础技能

目录 两两交换链表中的节点单链表加一链表加法使用栈实现使用链表反转实现 两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点…

关于深度学习中Attention的一些简单理解

Attention 机制 Attention应用在了很多最流行的模型中&#xff0c;Transformer、BERT、GPT等等。 Attention就是计算一个加权平均&#xff1b;通过加权平均的权值来自计算每个隐藏层之间的相关度&#xff1b; 示例 Attention 机制 Attention应用在了很多最流行的模型中&am…

基于深度学习的人脸专注度检测计算系统 - opencv python cnn 计算机竞赛

文章目录 1 前言2 相关技术2.1CNN简介2.2 人脸识别算法2.3专注检测原理2.4 OpenCV 3 功能介绍3.1人脸录入功能3.2 人脸识别3.3 人脸专注度检测3.4 识别记录 4 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的人脸专注度…

【机器学习】决策树与分类案例分析

决策树与分类案例分析 文章目录 决策树与分类案例分析1. 认识决策树2. 分类3. 决策树的划分依据4. 决策树API5. 案例&#xff1a;鸢尾花分类6. 决策树可视化7. 总结 1. 认识决策树 决策树思想的来源非常朴素&#xff0c;程序设计中的条件分支结构就是if-else结构&#xff0c;最…

【数据结构】复杂度

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、什么是数据结构二、什么是算法三、算法的效率四、时间复杂度4.1 时间复杂度的概念4…

【100天精通Python】Day72:Python可视化_一文掌握Seaborn库的使用《二》_分类数据可视化,线性模型和参数拟合的可视化,示例+代码

目录 1. 分类数据的可视化 1.1 类别散点图&#xff08;Categorical Scatter Plot&#xff09; 1.2 类别分布图&#xff08;Categorical Distribution Plot&#xff09; 1.3 类别估计图&#xff08;Categorical Estimate Plot&#xff09; 1.4 类别单变量图&#xff08;Cat…

远程IO:实现立体车库高效运营的秘密武器

随着城市的发展&#xff0c;车辆无处停放的问题变得越来越突出。为了解决这个问题&#xff0c;立体车库应运而生。立体车库具有立体空间利用率高、存取车方便、安全可靠等优点&#xff0c;成为现代城市停车的重要解决方案。 立体车库控制系统介绍 在立体车库中&#xff0c;控制…

基于51单片机的四种波形信号发生器仿真设计(仿真+程序源码+设计说明书+讲解视频)

本设计 基于51单片机信号发生器仿真设计 &#xff08;仿真程序源码设计说明书讲解视频&#xff09; 仿真原版本&#xff1a;proteus 7.8 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0015 这里写目录标题 基于51单片机信号发生…

简单明了!网关Gateway路由配置filters实现路径重写及对应正则表达式的解析

问题背景&#xff1a; 前端需要发送一个这样的请求&#xff0c;但出现404 首先解析请求的变化&#xff1a; http://www.51xuecheng.cn/api/checkcode/pic 1.请求先打在nginx&#xff0c;www.51xuecheng.cn/api/checkcode/pic部分匹配到了之后会转发给网关进行处理变成localho…

Android底层摸索改BUG(二):Android系统移除预置APP

首先我先提供以下博主博文&#xff0c;对相关知识点可以提供理解、解决、思考的 Android 系统如何预装第三方应用以及常见问题汇集android Android.mk属性说明及预置系统app操作说明系Android 中去除系统原生apk的方法 取消预置APK方法一&#xff1a; 其实就是上面的链接3&a…

Day 4 登录页及路由 (二) -- Vue状态管理

状态管理 之前的实现中&#xff0c;判断登录状态用了伪实现&#xff0c;实际当中&#xff0c;应该是以缓存中的数据为依据来进行的。这就涉及到了应用程序中的状态管理。在Vue中&#xff0c;状态管理之前是Vuex&#xff0c;现在则是推荐使用Pinia&#xff0c;在脚手架项目创建…

linux查看系统版本、内核信息、操作系统类型版本

1. 使用 uname 命令&#xff1a;这将显示完整的内核版本信息&#xff0c;包括内核版本号、主机名、操作系统类型等。 uname -a2. 使用 lsb_release 命令&#xff08;仅适用于支持 LSB&#xff08;Linux Standard Base&#xff09;的发行版&#xff09;&#xff1a;这将显示包含…

HCIE怎么系统性学习?这份HCIE学习路线帮你解决

华为认证体系覆盖ICT行业十一个技术领域共十三个技术方向的认证&#xff0c;今天我们分享的是其中最热门的数据通信方向的HCIE学习路线。 HCIE是华为认证体系中最高级别的ICT技术认证 &#xff0c;旨在打造高含金量的专家级认证&#xff0c;为技术融合背景下的ICT产业提供新的能…

JVS-BI数字大屏设计器:一站式解决方案

数字大屏介绍 数字大屏是当下数据展示、业务监控、指挥调度常见的业务表达形态&#xff0c;常有可视化的图表、效果装饰、事件操作等技术组成酷炫的效果展示。 配置入口 进入JVS-BI&#xff08;bi.bctools.cn&#xff09;&#xff0c;进入大屏页面&#xff0c;如下图所示 ①…

TypeScript之函数以及与JavaScript函数的区别

一、是什么 函数是JavaScript 应用程序的基础&#xff0c;帮助我们实现抽象层、模拟类、信息隐藏和模块 在TypeScript 里&#xff0c;虽然已经支持类、命名空间和模块&#xff0c;但函数仍然是主要定义行为的方式&#xff0c;TypeScript 为 JavaScript 函数添加了额外的功能&…

Docker 部署spring-boot项目(超详细 包括Docker详解、Docker常用指令整理等)

文章目录 DockerDocker的定义Docker有哪些作用Docker有哪些好处使用docker部署springboot项目安装docker创建Dockerfile镜像文件执行镜像文件(Dockerfile文件)查看Docker镜像启动容器查看Docker中运行的容器查看服务容器日志 Docker常用指令查看docker安装目录启动Docker停止Do…

无品牌国产PLC模块调试说明

地址30001对应的aiw9 30002对应aiw10 30003 aiw11 30004 aiw12 模块接线及拨码全部向下&#xff0c;对应的DeviceID为15地址 使用串口线链接的时候a要接b0 b接a0 要反着接才能有数据

金属压铸件自动化3D全尺寸测量设备自动外观检测三维检测-CASAIM

铸造作为现代装备制造工业的基础共性技术之一&#xff0c;铸件产品既是工业制造产品&#xff0c;也是大型机械的重要组成部分&#xff0c;被广泛运用在航空航天、工业船舶、机械电子和交通运输等行业。 铸件形状复杂&#xff0c;一般的三坐标或者卡尺圆规等工具难以获取多特征…