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

作者:汐栊

物联沃分享整理
物联沃-IOTWORD物联网 » SpringBoot深度解析:配置优先级、Bean管理、起步依赖、自动配置原理及源码追踪与自定义starter指南

发表回复