SpringBoot学习笔记
springboot是在spring的基础上的一款更加简便高效的开发框架,对很多技术都提供了默认的配置,实现了"just run"
springboot的特征:
- 创建独立的Spring程序
- 内嵌了Tomcat、Jetty、Undertow(无需部署成war)
- 启动器(starter)中包含了大量的依赖坐标,并且进行了版本的管理
- 提供了热部署工具
- 只需要少量的自定义配置去覆盖默认配置
springboot的启动器
springboot提供了启动器,启动器内包含了此启动器可能依赖的所有坐标,在创建一个springboot项目后,pom中会自动继承一个启动器的父工程,在父工程中,针对父工程的版本进行了大量的版本整合,所以我们不需要太过在意版本冲突问题。
例如
web启动器:spring-boot-starter-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
点进启动器看会发现web启动器包含了以下的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.3.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.3.3.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.3.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.8.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
由此,springboot的特点3的优势就展现了出来,不需要我们记住太多的坐标,只需要导入一个启动器即可导入大量的依赖,并且这些依赖的版本都是spring为我们整理好的,不需要担心版本冲突的问题
springboot的热部署
springboot的热部署实现了我们在开发的过程中,不需要重启项目就能使我们对代码的改动生效,可以节约一些时间。
原理
springboot在启动的时候会创建两个ClassLoader,其中一个(Loader1)用来加载那些不会改变的静态资源,另一个(Loader2)用来加载那些容易改变的资源,当我们开启了自动编译之后,springboot会将其做比对,如果代码发生了变动,那么就会创建一个新的Loader2去替换之前的Loader2,从而实现热部署。
但是如果发生变动的内容存在于/META-INF/maven, /META-INF/resources, /resources, /static, /public, or /templates这些目录下时,不会触发restert,而是触发live reload,这种live reload不会使项目重新编译,而是直接实现资源的替换。
热部署开启的方式
- 首先引入开发者工具的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
- 然后在idea设置里打开自动编译项目(默认关闭)
- 最后按ctrl+alt+shift+/,然后点击注册,在注册中勾选如下的选项即可实现热部署
springboot的自动配置
springboot为我们提供了大量的默认的配置,我们无需配置那些通用的内容,但是还是要了解boot的自动配置的原理。
springboot的自动配置原理
- 首先,springboot有一个启动类,这个启动类idea默认会放在我们域名下,并且以Application结尾
我们来分析以下这个主启动类,这个主启动类看起来就是一个一般的java类,有一个main程序的入口,此外就是一个SpringBootApplication注解和这个SpringApplication的run方法。
先来看看这个SpringBootConfiguration注解
在boot的源码中采取了SPI的思想,通过创建公共接口,实现实体类的热插拔。在boot的底层源码中遵循了一种规范,即如果在类路径下的META-INF下存在spring.factories文件,那么会被boot进行解析,解析之后通过反射的方式加载对应的实体类并存入IOC容器,此外,下图中的选择器会实现对spring.factories文件的筛选解析,没有引用指定实体类的自动配置类则会被过滤,实现一种基于接口的动态实现。
springboot的自动配置类采用了Conditional*注解,实现热插拔
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)//这个注解表示当此类不存在时,这个配置类就不会被加载进容器(即此类失效)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
springboot的自定义配置
有很多东西springboot不可能实现自动配置,或者有时候我们不需要一些自动配置,而是我们自定义一些配置,这个时候在yml文件里面到底写一些什么内容呢?
- 方式1:查看自动配置依赖中的spring.factories文件
然后在文件中找到EnableAutoConfig下面的配置类,找到你自己想要自己配置的配置类点进去(比如说RedisAutoConfiguration)
然后在这个配置类上面的EnableConfigurationProperties注解中找到对应的Properties,点进去就会看到我们可以自己配置的字段的名称
@ConfigurationProperties(prefix = "spring.redis")//这里使我们要在yml中输入的前缀名
public class RedisProperties {
/**
* Database index used by the connection factory.
*/
private int database = 0; //这些属性就是我们可以自定义的字段
/**
* Connection URL. Overrides host, port, and password. User is ignored. Example:
* redis://user:password@example.com:6379
*/
private String url; //自己配置uil
/**
* Redis server host.
*/
private String host = "localhost"; //自己配置ip地址等等
-
方式2:查看官方文档
yml属性绑定
yml中可以配置各种数据类型,而且可以通过注解实现对实体类中属性的注入
ConfigurationProperties注解绑定
ConfigutationProperties注解主要用于多个属性的绑定,例如在一个类中的所有属性绑定
方式1:set方法注入
在yml文件中配置如下属性
# 这里采用了松散绑定,可以自动匹配大小写 - _
yml:
test:
name: 周杰伦
age: 22
son:
name: 周杰
age: 10
然后在需要注入属性的实体类中使用ConfigurationProperties注解
@Conmonent//这种方式一定要手动将这个加入IOC
@Data
@ConfigurationProperties("yml.test")//set方法注入属性,在配置类中前缀不支持驼峰,支持羊肉串模式a-b
@Validated//开启jsr303校验
public class TestYml {
private String name;
private Integer age;
private Son son=new Son();//注意这里是属性注入,不是注入对象,所以这里要有对象实例才能实现注入属性
@Data
class Son{
private String name;
private Integer age;
}
}
注意: 如果一个配置类只配置@ConfigurationProperties 注解,而没有使用@Component,那么在 IOC 容器中是获取不到 properties 配置文件转化的 bean。说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了启用注入
方式2:构造函数注入
yml文件中的配置不变
要使用构造函数绑定,必须使用@EnableConfigurationProperties或配置属性扫描启用类。 不能对由常规 Spring 机制创建的 Bean 使用构造函数绑定(例如@Component Bean、通过 @Bean 方法创建的 Bean 或使用@Import 加载的 Bean)
@Data
@ConfigurationProperties("yml.test")//set方法注入属性,在配置类中前缀不支持驼峰,支持羊肉串模式a-b
@ConstructorBinding//构造函数注入属性,需要额外的EnableConfigurationProperties注解开启属性注入,并且不需要加入ioc容器
@Validated//jar303属性校验
public class TestYml {
private String name;
private Integer age;
public TestYml(String name, Integer age) {
this.name = name;
this.age = age;
}
}
使用@EnableConfigurationProperties来扫描上面的类
@RestController
@EnableConfigurationProperties(TestYml.class)//开启构造函数注入,并且传入要注入的类的class
public class TestController {
@Autowired
private TestYml test;
}
以前我们的纯注解的配置都需要在配置类中配置bean,而从SpringBoot2.2.1开始我们可以在非配置类的内部定义Bean加入IOC。
方式3:第三方组件注入
除了使用@ConfigurationProperties 注释类之外,还可以在 public@Bean 方法上使用它。 如果要将属性绑定到不在您控制范围内的第三方组件 依然采用之前的案例的 yaml 配置 创建一个其他组件类
@Data
public class AnotherComponent {
private boolean enabled;
private InetAddress remoteAddress;
}
创建 MyService
@Component
public class MyService {
@ConfigurationProperties("acme") //第三方组件注入
@Bean
public AnotherComponent anotherComponent(){
return new AnotherComponent();
}
}
通过测试可以获得 AnotherComponent 组件的实例对象。
Value注解绑定
value注解主要用于单个属性的绑定