原理篇..
配置优先级
SpringBoot 中支持三种格式的配置文件:
application.properties,application.yml,application.yaml
那么当我们同时配置这三份配置文件的时候,哪个文件会生效呢?
答案是:properties > yml > yaml
注意:虽然 springboot 支持多种格式配置文件,但是在项目开发时,推荐统一使用一种格式的配置 (yml是主流)
除了这三个之外,还有两个外部配置:java系统属性 和 命令行参数
这两个外部配置都比那三个内部配置文件优先级高,其中命令行参数优先级是最高的。
Bean 管理
Bean作用域
Spring 支持五种作用域,后三种在 web 环境才生效
单例:
注意:默认 singleton 的 bean,在容器启动时被创建,可以使用 @Lazy 注解来延迟初始化(延迟到第一次使用时)。
注意:实际开发当中,绝大部分的 Bean 是单例的,也就是说绝大部分 Bean 不需要配置 scope 属性。
面试题1:Spring 容器的 bean 是单例的还是多例的?单例的 bean 是什么时候实例化的?
* 默认是单例的
* 单例的 bean,默认是项目启动时实例化的(通过 @Lazy 可以延迟初始化)
面试题2:Spring 容器的 bean 是线程安全的吗?
* bean的线程安全取决于 bean 的状态及 bean 的作用域
* 单例 bean:如果是无状态的 bean,内部不保存任何状态信息,则是线程安全的
* 单例 bean:如果是有状态的 bean,内部会保存状态信息,多个线程同时操作该 bean 时,可能出现数据不一致的问题,这样的 bean 是线程不安全的
第三方 Bean
如果要管理的 bean 对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明 bean 的,就需要用到 @Bean 注解
若要管理第三方 bean 对象,建议对这些 bean 进行集中分类配置,可以通过 @Configuration 注解声明一个配置类。
注意:如果第三方 bean 需要依赖其他 bean 对象,直接在 bean 定义方法中设置形参即可,容器会根据类型自动装配。
注意:通过 @Bean 注解的 name 或 value 属性可以声明 bean 的名称,如果不指定,默认 bean 的名称就是方法名。
SpringBoot 原理
起步依赖
原理就是 maven 当中的依赖传递
自动配置
SpringBoot 的自动配置就是当 spring 项目启动后,一些配置类,bean 对象就自动存入到了 IOC 容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作
自动配置实现方案一:
我们首先要在我们自己的项目的 pom 文件引入这个工具包的依赖
然后将我们需要的第三方工具包里面的实现类加上 @Component 注解
最后我们要在自己项目的启动类上添加我们要扫描的包,因为它默认扫描的是启动类所在的包和它的子包。
自动配置实现方案二:
@Import 导入。@Import 导入的类会被 Spring 加载到 IOC 容器中,导入形式主要有以下几种:
1:导入 普通类
2:导入配置类(配置类中所配置的类都会导入到 IOC 容器当中)
3:导入 ImportSelector 接口实现类
不过上面的三种导入方式都不太人性化,我们可以直接在我们项目的启动类中导入注解
@EnableHeaderConfig,这个注解里面封装的就是上面的第三种导入方法
源码跟踪
@SpringBootApplication
该注解标识在 SpringBoot 工程引导类上,是 SpringBoot 中最最最重要的注解。该类由三个部分组成:
这个 imports 文件里有 152 个配置类,那么这 152 个类里面的所有声明的 Bean 都会导入到 IOC 容器中吗?答案是否定的,我们可以发现每个 Bean 对象后面都会跟着一个 @Conditional 开头的注解,这个注解就是决定是否要将该 Bean 对象放入容器的关键;
自动配置 - @Conditional
作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的 bean 对象到 Spring IOC 容器中。
位置:方法,类
@Conditional 本身是一个父注解,派生出大量的子注解:
@ConditionalOnClass:判断环境中是否有对应字节码文件,才注册 bean 到 IOC 容器
@ConditionalOnMissingBean:判断环境中没有对应的 bean (类型 或 名称),才注册 bean 到 IOC 容器。
@ConditionalOnProperty:判断配置文件中有对应属性和值,才注册 bean 到 IOC 容器。
所以最后总结一下:自己定义自动配置类的核心是什么?如何完成自动配置?
1:定义自动配置类;
2:将自动配置类配置在
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中;
自定义 starter
什么是starter 呢?就是我们引入进来的依赖
场景:在实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在 SpringBoot 项目中,一般会将这些公共组件封装为 SpringBoot 的 starter(包含了起步依赖和自动配置的功能)
需求:自定义 aliyun-oss-spring-boot-starter,完成阿里云 OSS 操作工具类 AliyunOSSOperator 的自动配置。
目标:引入起步依赖之后,要想使用阿里云 OSS,注入 AliyunOSSOperator 直接使用即可。
步骤:
1:创建 aliyun-oss-spring-boot-started 模块
2:创建 aliyun-oss-spring-boot-autoconfigure 模块,在 starter 中引入该模块
3:在 aliyun-oss-spring-boot-autoconfigure 模块中定义自动配置功能,并自定义配置文件:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
步骤一:
步骤二:
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId><version>0.0.1-SNAPSHOT</version></dependency>
步骤三:
将阿里云的依赖引入到 autoconfiguer模块的 pom 文件中
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency>
引入工具类
创建一个自动配置类
package com.aliyun.oss;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableConfigurationProperties(AliyunOSSProperties.class)
public class AliyunOssAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties aliyunOSSProperties) {return new AliyunOSSOperator(aliyunOSSProperties);}
}
在 resources 目录下创建这个配置文件,注意这里的目录和文件名一定不能错
com.aliyun.oss.AliyunOssAutoConfiguration
我们要用时只需要在该项目的 pom 文件中引入 starter 的依赖就可以,别的会传递进来