当前位置: 首页 > news >正文

SpringBoot源码分析

一:简介

  1. 由Pivotal团队提供的全新框架
  2. 其设计目的是用来简化新Spring应用的初始搭建以及开发过程
  3. 使用了特定的方式来进行配置
  4. 快速应用开发领域

二:运行原理以及特点

运行原理:

SpringBoot为我们做的自动配置,确实方便快捷,今天来了解一下它的原理:
在这里插入图片描述
特点:

  1. 可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
  2. 内嵌Tomcat或Jetty等Servlet容器;
  3. 提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
  4. 尽可能自动配置Spring容器;
  5. 提供准备好的特性,如指标、健康检查和外部化配置;
  6. 绝对没有代码生成,不需要XML配置。

三:重点了解

  1. 约定优于配置
  2. 开箱即用
  3. 程序和注解

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源码分析

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

约数个数和约数之和算法总结

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

数据结构-怀化学院期末题(322)

图的深度优先搜索 题目描述&#xff1a; 图的深度优先搜索类似于树的先根遍历&#xff0c;是树的先根遍历的推广。即从某个结点开始&#xff0c;先访问该结点&#xff0c;然后深度访问该结点的第一棵子树&#xff0c;依次为第二顶子树。如此进行下去&#xff0c;直到所有的结点…...

小手也能用的高性能鼠标,自定义空间还挺高,雷柏VT9Pro mini上手

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

CDN加速原理详解

一、CDN加速是什么意思 CDN是Content Delivery Network&#xff09;英文首字母的缩写&#xff0c;中文翻译为内容分发网络&#xff0c;由于CDN是为加快网络访问速度而被优化的网络覆盖层&#xff0c;因此被形象地称为”网络加速器”&#xff0c;即CDN加速。CDN加速是通过将网站…...

sqlachemy orm create or delete table

sqlacehmy one to one ------detial to descript 关于uselist的使用。如果你使用orm直接创建表关系,实际上在数据库中是可以创建成多对多的关系,如果加上uselistFalse 你会发现你的orm只能查询出来一个&#xff0c;如果不要这个参数orm查询的就是多个&#xff0c;一对多的…...

科普小米手机、华为手机、红米手机、oppo手机、vivo手机、荣耀手机、一加手机、realme手机如何设置充电提示音

用空空鱼就可以设置&#xff0c;上面还有很多提示音素材还可以设置满电和低电提醒...

zookeeper应用场景之分布式的ID生成器

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

Java--Spring项目生成雪花算法数字(Twitter SnowFlake)

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

紫光展锐M6780丨画质增强——更炫的视觉体验

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

控制el-table的列显示隐藏

控制el-table的列显示隐藏&#xff0c;一般的话可以通过循环来实现&#xff0c;但是假如业务及页面比较复杂的话&#xff0c;list数组循环并不好用。 在我们的页面中el-table-column是固定的&#xff0c;因为现在是对现有的进行维护和迭代更新。 对需要控制列显示隐藏的页面进…...

2024上海国际冶金及材料分析测试仪器设备展览会

2024上海国际冶金及材料分析测试仪器设备展览会 时间&#xff1a;2024年12月18&#xff5e;20日 地点&#xff1a;上海新国际博览中心 ◆ 》》》组织机构&#xff1a; 主办单位&#xff1a;全联冶金商会、中国宝武钢铁集团有限公司、上海市金属学会 支持单位&#xff…...

商业定位,1元平价商业咨询:豪威尔咨询!平价咨询。

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

2. Presto应用

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

工业级安卓PDA超高频读写器手持掌上电脑,RFID电子标签读写器

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

Prompt提示工程上手指南:基础原理及实践(一)

想象一下&#xff0c;你在装饰房间。你可以选择一套标准的家具&#xff0c;这是快捷且方便的方式&#xff0c;但可能无法完全符合你的个人风格或需求。另一方面&#xff0c;你也可以选择定制家具&#xff0c;选择特定的颜色、材料和设计&#xff0c;以确保每件家具都符合你的喜…...

Redis如何保证缓存和数据库一致性?

背景 现在我们在面向增删改查开发时&#xff0c;数据库数据量大时或者对响应要求较快&#xff0c;我们就需要用到Redis来拿取数据。 Redis&#xff1a;是一种高性能的内存数据库&#xff0c;它将数据以键值对的形式存储在内存中&#xff0c;具有读写速度快、支持多种数据类型…...

学完C/C++,再学Python是一种什么体验?

你好&#xff0c;我是安然无虞。 文章目录 变量及类型变量类型动态类型特性 注释输入输出通过控制台输出通过控制台输入 运算符算术运算符关系运算符逻辑运算符赋值运算符 条件循环语句条件语句语法格式代码案例缩进和代码块空语句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 …...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...