SpringBoot原理篇

📅 2026/7/17 7:15:10 👁️ 阅读次数 📝 编程学习
SpringBoot原理篇

一,Springboot配置优先级

1,三种内部配置文件

一)文件类型

properties文件,yml文件,yaml文件

二)文件类型执行顺序

properties文件 > yml文件 > yaml文件

建议:配置文件统一使用同一种格式,yml文件最经常使用

2,两种外部配置指令

一)文件格式

java系统属性格式

-Dserver.port=9000 格式:-D配置文件名=配置属性

命令行参数格式

--server.port=10010 格式:--配置文件名=配置属性

二)配置方式

点击edit configuration

选择要配置的项目,配置VM option和program arguments,假设没有这两个,可以点击Mondify option,选择add VM option就行

细节:这个配置方法只能在idea软件使用,假设运行这个代码的jar包,只有配置文件有效,但如果不想使用配置文件的内容,就可以在执行代码上添加指令

三)执行优先顺序

命令参数 > java系统属性

四)所有顺序排序

命令参数 > java系统属性 > properties文件 > yml文件 > yaml文件

五)配置作用

可以执行maven打包指令package,将代码打包成jar包

然后执行命令行,运行jar包

java -Dserver.port=9000 -jar tilas-web-management-0.0.1-SNAPSHOT.jar --server.port=10010

格式:java java系统属性(选填) jar包文件名 命令参数(选填)

需要引入依赖spring-boot-maven-plugin,如果是使用springboot官方的文件,官方有提前引入

二,bean管理

1,bean的作用域

关键了解前两个的运行时机以及作用

细节:假设没有指定bean的类型,默认就是singleton

2,单例和多例bean

一)单例bean

单例bean的使用时机,就是如果没有数据的保存,因为这样就不会有线程安全的问题,优势:不用多次创建目标类和销毁,提高运行效率

假设需要数据保存,那么多个线程就会公用一个数据,导致数据无效化

二)多例bean

多例bean的使用时机,就是需要数据的存储,因为这样,每一个新的线程,就会创建一个新的bean供其使用,就不会有线程安全的问题,优势:多个用户多条线程使用的数据相互独立,互不影响,但是需要多次创建和消除目标类,效率低

3,第三方bean

假设想要将第三方工具引入我们的项目,无法使用直接注入依赖的方式注入工具类,因为第三方的工具类是无法编辑的,所以需要新的注解@Bean添加依赖

//注解新的bean交给ioc容器管理 //一旦交给ioc管理,那么就会自动调配aliyunOSSProperties,无需添加注解@Autowired @Bean public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties aliyunOSSProperties) { return new AliyunOSSOperator(aliyunOSSProperties); }

假设第三方类为AliyunOSSProperties,那么就将上面的方法写到启动类里面,那么就会将这个方法添加到ioc容器内,自动配对类

但是我们希望启动类的方法单一,所以不要将第三方bean的引入写在启动类上面,就需要创建一个新的类用于处理这个方法,使用注解@Configuration,表示配置类

@Configuration public class CommonConfig { //注解新的bean交给ioc容器管理 //一旦交给ioc管理,那么就会自动调配aliyunOSSProperties,无需添加注解@Autowired @Bean public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties aliyunOSSProperties) { return new AliyunOSSOperator(aliyunOSSProperties); } }

三,SpringBoot原理

1,起步依赖-原理

引入某个依赖,就会将其他常用的依赖一同引入,减少代码的配置时间,提高效率

是根据maven的依赖传递

2,自动配置

一)自动配置是什么

SpringBoot的自动配置就是当Spring项目启动后,一些配置类,bean对象就会自动存入ioc容器中,不需要手动声明,从而简化开发,省去繁琐的配置操作

二)自动配置的方案

1)方案一,导入普通类

在启动类上面声明手动扫描注解@ComponentScan(basePackages = {包名字符串数组})

缺点:后续一旦有多个第三方工具包,就需要我们手动扫描,并且需要我们程序员了解第三方包名

性能低,扫描越多的包,消耗时间越长

@SpringBootApplication //springBootApplication具备组件扫描的功能,但是只能扫描当前包以及子包下的类 //所以需要手动配置扫描的包名,一旦配置扫描范围,那么原来的扫描范围就会失效 @ComponentScan(basePackages = {"com.itheima","com.example"}) public class SpringbootWebConfigApplication { public static void main(String[] args) { SpringApplication.run(SpringbootWebConfigApplication.class, args); } }
2)方案二,导入配置类
@Configuration public class HeaderConfig { @Bean public HeaderParser headerParser(){ return new HeaderParser(); } @Bean public HeaderGenerator headerGenerator(){ return new HeaderGenerator(); } }

也需要我们了解第三方的配置类的类名,不利于开发

@Import(HeaderConfig.class)//配置类,就是有注解@Configuration的类

3)方案三,导入ImportSelector接口实现类
public class MyImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.example.HeaderConfig", "com.example.TokenParser"}; } }

importSelect接口的作用就是可以批量注入工具类

优势就是只要第三方开发人员配置好注入的包名,使用者直接使用这个类的名字就行

@Import(MyImportSelector.class)//ImportSelector的实现类,实现批量导入

4)方案四,@EnableXxx注解,封装@Import注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Import(MyImportSelector.class) public @interface EnableHeaderConfig { }

使用@Import注解,将上面第三种方案给封装到我们自定义的注解上,这样使用者就直接可以使用,也不需要知道importSelect实现类的包名,使用自定义注解@EnableHeaderConfig

三)小结

3,自动配置,源码跟踪

一)@SpringBootApplication启动类源码跟踪

自动配置在springboot项目中,启动位置就是我们的启动类注解上@SpringBootApplication

@SpringBootApplication注解内部封装了其他三个重要的注解

第一个注解@SpringBootConfiguration,底层其实就是封装了注解@Configuration,所以启动类注解底层就是配置类

第三个注解@ComponentScan,就是扫描注解,所以启动类注解才具备扫描功能

第二个注解@EnableAutoConfiguration表示开启自动配置的开关,而Enable这种字母开头,就表示底层一定会封装@Import注解

而AutoConfigurationImportSelector.class底层是ImportSelector的实现类,importSelector底层可以批量注入第三方工具类,importSelector的结果返回值就是String类型的数组,数组内容就是第三方工具类的全类名

而一下就是AutoConfigurationImportSelector的实现方法,返回类型就是String数组

再次进入getAutoConfigurationEntry,其中主要的参数configurations和exclusions分别表示需要注入的所有全类名,排除不需要注入的全类名

进入getCandidateConfigurations方法内,就是返回需要注入的全类名

而下面的这个就是记录全类名的文件地址

下面就是这个文件的记录内容,所有需要注入的方法的全类名

二)注入条件设置

而因为有太多的第三方类需要注入,所以在真正的项目中类的注入并不是全部注入,需要达到某些条件才可以实现自动注入,所以就出现注解@Conditional,就表示需要达到某些条件才会注入

三)小结

3,自定义starter

一)功能

可以包装某个比较单一重复的方法,将方法的全类名添加到指定路径指定名字的文件内,那么只要使用@Autowired注解,就能直接将方法注入,例如:aliyun的文件上传

二)实现流程

1)创建starter模块

这个starter模块唯一的功能就是注入依赖,将主要实现功能的模块注入starter模块

2)创建autoconfigure模块

这个autoconfigure模块主要就是实现功能,其中主要功能的类不需要使用@Component注入到bean容器,这个功能模块也不需要启动类

然后创建一个autoconfigure类,注明是配置类,并且需要@bean注解将这个类添加到容器内,创建一个函数,将我们需要调用的功能类返回结果,那么就会因为有@bean注解自动添加到ioc容器内

3)创建文件

文件路径必须是META-INF.spring,不能有任何不一样的地方,这样才会被自动匹配注入,文件内容必须是autoconfigure的全类名,这样启动时才会自动将这个全类名添加到importSelecter进行批量注入,文件名有点复杂,直接看别人写好的然后复制就行

四,maven高级

1,分模块设计

一)设计格式

二)写法格式

将其他模块与主模块分开设计,然后在主模块的pom.xml文件内引入其他模块的依赖

二)优势

方便维护,每个模块只实现自己的功能,方便查找问题所在模块

方便开发,能够实现多人开发一个工程,最后由主模块同一依赖注入

2,继承

一)继承关系

1)概念

继承描述的是两个工程之间的关系,与java中的继承相似,子继承是可以继承父工程的配置信息,一般父工程配置的都是子工程的公共配置信息

作用:同一依赖管理,简化配置信息

实现:<parent>...</parent>

工程之间继承只能单继承,但是可以和java代码继承一样使用多重继承

2)实现流程

1,创建maven模块tlias-parent,该工程就是父工程,设置打包方式为pom(默认是jar包)

jar包:普通模块打包,springboot项目基本都是java包(内嵌tomcat进行)

war包:普通web程序打包,需要部署在外部tomcat服务器中运行

pom包:父工程或聚合工程,该模块不写代码,仅进行依赖管理

2,在子工程的pom.xml文件配置继承关系

3,在父工程配置各个工程共有的依赖

3)细节

二)版本锁定

1)作用

可以直接在父工程中统一指定所有依赖的版本,那么子工程在引入依赖时就不需要指定版本

2)写法
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 设置所有版本号在最上面,这样方便查找修改--> <lombok.version>1.18.34</lombok.version> <spring-boot-starter.version>3.2.8</spring-boot-starter.version> <aliyun-sdk-oss.version>3.18.4</aliyun-sdk-oss.version> <jaxb-api.version>2.3.1</jaxb-api.version> <activation.version>1.1.1</activation.version> <jaxb-runtime.version>2.3.3</jaxb-runtime.version> <jjwt.version>0.9.1</jjwt.version> <mybatis-spring-boot-starter.version>3.0.3</mybatis-spring-boot-starter.version> <mybatis-spring-boot-starter-test.version>4.0.1</mybatis-spring-boot-starter-test.version> <pagehelper.version>1.4.7</pagehelper.version> </properties>

3,聚合

一)目的

假设我们在打包jar包,我们使用分模块设计的方式,打包jar包他就需要到本地仓库查找,但是前提还需要我们手动把其他模块下载到本地仓库,太繁琐,所以需要聚合操作,把需要使用的模块聚合一起,然后直接打包就可以了

二)实现

1,需要一个聚合工程,其实就是父工程,在聚合工程内设置需要聚合的模块的相对地址

2,使用标签<modules>

<!-- 聚合模块--> <modules> <module>../tilas-pojo</module> <module>../tilas-web-management</module> <module>../tilas-utils</module> </modules>

4,私服

就是假设多个公司需要使用同一个模块或者项目,但是我们只能将模块保存到本地仓库,而其他的公司无法获取到,那么就需要私服,相当于在多个公司之间创建一个仓库公共使用

私服仓库分为三个部分,central仓库是从中央仓库下载下来的模块依赖,release仓库是表示稳定版本,可以正式发布,snapshot仓库表示快照版本,就是不稳地版本

配置访问私服和上传私服有点麻烦,直接看第151集就行https://www.bilibili.com/video/BV1yGydYEE3H?spm_id_from=333.788.videopod.episodes&vd_source=b430d058955f32bb76f01d965d0e93df&p=151