SpringBoot深度解析:配置优先级、Bean管理、起步依赖、自动配置原理及源码追踪与自定义starter指南
目录
SpringBoot原理篇:
配置文件优先级:
Bean管理:
Bean的作用域:
第三方Bean:
注意事项:
起步依赖的原理:
自动配置原理:
自动配置:
方案一:
方案二:
个人理解的SpringBoot的自动化配置原理:
自动配置-@Conditionnal:
自定义starter:
SpringBoot原理篇:
配置文件优先级:
SpringBoot中支持的三种格式的配置文件:
1.properties:
server.port=8081
2.yml:
server:
port: 8082
3.yaml:
server:
port: 8083
优先级:properties>yml>yaml。
虽然springboot支持多种格式配置文件,但是在项目开发时,推荐统一使用一种格式的配置(yml是主流)。
SpringBoot除了支持配置文件属性配置,还支持Java系统属性配置和命令行参数的方式进行属性配置。
Java系统属性:
-Dserver.port=9000
命令行参数:
--server.port=10010
开发完毕打成jar包可以设置Java系统属性和命令行参数:
1.执行maven打包指令package
2.执行java指令,运行jar包
cmd中运行jar包可以改变配置参数:
java -Dserver.port=9000 -jar 包名 --server.port=10010
SpringBoot配置优先级(高->低):
1.命令行参数(–xxx=xxx)
2.java系统属性(-Dxxx=xxx)
3.application.properties
4.application.yml
5.application.yaml
Bean管理:
Bean的作用域:
作用域 说明
signleton 容器内同名称的bean只有一个实例(单例)(默认)
prototype 每次使用该bean时会创建新的实例(非单例/多例)
request 每个请求范围内都会创建新的实例(web环境中,了解)
session 每个会话范围内都会创建新的实例(web环境中,了解)
application 每个应用范围内都会创建新的实例(web环境中,了解)
方法实现:
@Scope("prototype")
@RequestMapping("/depts")
@RestController
public class DeptController{
}
默认bean是单例的,在容器启动时被创建,可以用@Lazy注解来延迟初始化(延迟到第一次使用时)。
如果是无状态的bean用单例的bean,不储存数据
如果是有状态的bean用多例的bean,批量处理本次数据
单例的bean:如果是无状态的bean,内部不保存任何状态信息,则是线程安全的
单例的bean:如果是有状态的bean,内部会保存状态信息,多个线程同时操作该bean时,可能会出现数据不一致的问题,这样的bean则是线程不安全的。
第三方Bean:
如果要管理的bean对象来自于第三方(不是自定义的),是无法用@Component及其衍生注解声明bean的,就需要用到@Bean注解。
若要管理第三方bean对象,建议对这些bean进行集中管理,可以通过@Configuration注解声明一个配置类。
方法实现:
@Configuration
public class OSSConfig{
@Bean
public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties ossProperties){
return new AliyunOSSOperator(ossProperties);
}
}
注意事项:
1.如果第三方bean需要依赖其他bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配
2.通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean名称是方法名。
起步依赖的原理:
maven中的依赖传递
自动配置原理:
SpringBoot的自动配置就是当Spring项目启动后,一些配置类,bean对象就自动存入到了IOC容器中,不需要我们手动声明,从而简化了开发,省去了繁琐的配置操作。
自动配置:
第三方依赖中使用@Component及其衍生注解不生效,因为组件扫描不到所在包及其子包以外的:
解决方案方案:
方案一:
1.在想被使用的方法上加上@Component。
2.在启动类中配置组件扫描的路径@ComponentScan("包名","包名")
但是这种方法要配置的很多很繁琐。
方案二:
启动类中@Import导入。@Import导入的类会被Spring加载到IOC容器中,导入形式主要有以下几种:
1.导入普通类
2.导入配置类
3.导入ImportSelector接口实现类
public class MyImportSelector implements ImportSelector{
public String[] selectImports(AnnotationMetadata importingClassMetadata){
return new String[]{"类名",""}
}
}
4.@EnableXxxx注解,封装@Import注解
@Import(MyImportSelector.class)
public @interface EnableHeaderConfig{
}
启动类注解标识在SpringBoot工程引导上,是SpringBoot中最重要的注解。该注解由三个部分组成:
1.@SpringBootConfiguration:该注解与@Configuration注解作用相同,用来声明当前也是一个配置类。
2.@ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包。
3.@EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解。
个人理解的SpringBoot的自动化配置原理:
启动类的注解@SpringBootApplication底层封装了@EnableAutoConfiguration注解,在@EnableAutoConfiguration注解底层又封装了@Import注解,@Import注解当中导入了一个@ImportSelector注解的实现类AutoConfigurationImportSelector.class,实现类AutoConfigurationImportSelector.class实现了注解的一个方法selectImports,方法selectImports返回值是一个String类型数组,String类型数组封装了需要通过Import注解批量导入的全类名,通过注解@ConditionalOnMissingBean确定哪些需要导入哪些不需要导入。
自动配置-@Conditionnal:
作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring IOC容器中。
位置:方法,类。
@Conditional:本身是一个父注解
@ConditionalOnClass:判断环境中是否有对应字节码文件,有才注册bean到IOC容器。
@ConditionalOnMissingBean:判断环境中有没有对应的bean(类型或名称),才注册bean到IOC容器
@ConditionalOnProperty:判断配置文件中有对应属性和值,配置了才注册bean到IOC容器。
自定义starter:
自动配置+起步依赖:
需求:自定义aliyun-oss-spring-boot-starter,完成阿里云OSS操作工具类AliyunOSSOperator的自动配置
目标:引入起步依赖之后,要想使用阿里云OSS,注入AliyunOSSOperator直接使用即可。
步骤:
1.创建aliyun-oss-spring-boot-starter模块(依赖管理功能)
2.创建aliyun-oss-spring-boot-autoconfigure模块(自动配置功能),在stater中引入模块
3.在aliyun-oss-spring-boot-autoconfigure模块中的定义自动配置功能,并定义自动配置文件 META-INF/spring/xxxx.imports
作者:汐栊