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