一.什么是Springboot
1.1 springboot以约定大于配置的核心思想
spring boot的优点
业务:service:userService:===>模块!
springmvc,controller===>提供接口!
http:rpc
用户下单:controller!
消息队列:
仓库冻结:资金冻结;验证;购买成功,仓库数量减少,仓库解冻,资金解冻
高类聚,低耦合
二.第一个springboot程序
jdk1.8
maven3.6.1
springboot:最新版
idea
官方:提供了一个快速生成的网站!Spring Initializr
- 可以在spring官网直接下载后,导入idea开发
- 直接使用idea创建一个新的springboot项目
官方文档:Spring Boot Reference Guide
三.原理初探
3.1自动配置
3.1.1pom.xml
核心依赖
<dependencyManagement>
<!-- 所依赖的框架 版本仓库-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
不需要指定版本,因为有版本仓库
启动器
<!-- 启动器,会帮我们自动导入web环境所有的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
- 启动器:说白了就是springboot的启动场景
- 比如spring-boot-starter-web,他会帮助我们自动导入web环境所有的依赖!
- springboot会将所有的功能场景,都变成一个个的启动器
- 我们使用什么功能,就只需要找到对应的启动器就可以了 starters
3.1.2主程序
//@SpringBootApplication:标注这个类是一个springboot的应用
@SpringBootApplication
public class Springboot2Application {
public static void main(String[] args) {
//将springboot应用启动
SpringApplication.run(Springboot2Application.class, args);
}
}
注解@SpringBootApplication分析
@SpringBootConfiguration:springboot的配置
@Configuration:spring的配置类
@Component:说明这也是一个spring的组件
@EnableAutoConfiguration:自动配置
@AutoConfigurationPackage:自动配置包
@Import({Registrar.class}):自动配置'包注册'
@Import({AutoConfigurationImportSelector.class}):自动配置导入选择器
//获取所有的配置
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
META-INF/spring.factories:自动配置核心文件
META-INF/spring.factories
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
springboot加载的思维导图点下面的链接查看
https://www.processon.com/view/link/60dd44685653bb2a8d098b82
结论:springboot所有自动配置都在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动配置就会生效,然后配置成功!
- springboot在启动的时候,会从类路径下/META-INF/spring.factories获取指定的值
- 将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置
- 以前需要我们自动配置的东西,现在springboot帮我们做了
- 整合javaee,解决方法和自动配置的东西都在spring-boot-autoconfigure-2.3.7.RELEASE.jar这个包下面
- 他会把所有需要导入的组件,以类名的方式返回,这些组件会被添加到容器
- 容器中也会存在非常多的xxxAutoConfiguration文件(@bean),就是这些类给容器中导入了这个场景需要的所有组件;并自动配置,@Configuration,javaConfig!
- 有了自动配置类,免去了我们手动编写配置注入功能主键等工作。
分析SpringApplication.run()
分析部分主要分两部分,一部分是SpringApplication的实例化,一部分是run方法的执行
SpringApplication
这个类主要做了以下四件事情:
1、推断应用的类型是普通的项目还是Web项目
2、查找并加载所有可用初始化器 , 设置到initializers属性中
3、找出所有的应用程序监听器,设置到listeners属性中
4、推断并设置main方法的定义类,找到运行的主类
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
// ......
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances();
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
原文链接:https://blog.csdn.net/qq_33369905/article/details/106647293
关于springboot的理解:自动装配,run()
四.YAML
4.1yml的配置
@ConfigurationProperties(prefix="person")有可能会报红,需要去官网下载以下,添加到pom.xml(maven和gradle都有,一下是maven的)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
#对空格的要求十分高
server:
port: 8080
#普通的key-value
name: lianhua
#对象
student:
name: lianhua
age: 18
#行内写法
student1: {name:lianhua01,age:18}
#数组
pets:
- cat
- dog
- pig
pets1: [cat,dog,pig]
结果如下:
松散绑定:yml中的last-name可以与实体类中的lastName是一样的,可以绑定。-后面跟着的字母默认为大写
JSR303数据校验:这个就是我们可以在字段上增加一层过滤器验证,可以保证数据的合法性
复杂类型封装:yml中可以封装对象,使用@value就不支持了
结论:
配置yml和配置properties都可以获取到值 , 强烈推荐 yml;
如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;
如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties,不要犹豫!
4.2JSR303数据校验
相关验证的注解如下:
配置文件加载顺序目录如下:
多环境配置:
五,原理的再次整理
5.1自动装配的流程
我们进入一个xxxAutoConfiguration可以看到,这些类里面都有一些注解
//表示这是一个配置类
@Configuration(
proxyBeanMethods = false
)
//自动配置属性:ServerProperties
@EnableConfigurationProperties({ServerProperties.class})
//spring底层注解:根据不同的条件判断当前配置或者类是否生效
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
prefix = "server.servlet.encoding",
value = {"enabled"},
matchIfMissing = true
)
其中自动配置属性,可以找到对应的类,可以看到这些类可以跟配置文件绑定,通过配置文件注入值。
5.2自动配置原理
狂神说的原理性粘贴
我们以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;
//表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件;
@Configuration
//启动指定类的ConfigurationProperties功能;
//进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来;
//并把HttpProperties加入到ioc容器中
@EnableConfigurationProperties({HttpProperties.class})
//Spring底层@Conditional注解
//根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效;
//这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(
type = Type.SERVLET
)
//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnClass({CharacterEncodingFilter.class})
//判断配置文件中是否存在某个配置:spring.http.encoding.enabled;
//如果不存在,判断也是成立的
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
@ConditionalOnProperty(
prefix = "spring.http.encoding",
value = {"enabled"},
matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
//他已经和SpringBoot的配置文件映射了
private final Encoding properties;
//只有一个有参构造器的情况下,参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this.properties = properties.getEncoding();
}
//给容器中添加一个组件,这个组件的某些值需要从properties中获取
@Bean
@ConditionalOnMissingBean //判断容器没有这个组件?
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
return filter;
}
//。。。。。。。
}
一句话总结 :根据当前不同的条件判断,决定这个配置类是否生效!
一但这个配置类生效;这个配置类就会给容器中添加各种组件;
这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
配置文件能配置什么就可以参照某个功能对应的这个属性类
5.3.@Conditional
了解完自动装配的原理后,我们来关注一个细节问题,自动配置类必须在一定的条件下才能生效;
@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
那么多的自动配置类,必须在一定的条件下才能生效;也就是说,我们加载了这么多的配置类,但不是所有的都生效了。
我们怎么知道哪些自动配置类生效?
我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;
#开启springboot的调试类
debug=true
Positive matches:(自动配置类启用的:正匹配)
Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)
Unconditional classes: (没有条件的类)
5.4.原理梳理
@SpringBootApplication里面的思维导图如下https://www.processon.com/view/link/60dd44685653bb2a8d098b82
从这个思维导图可以看出,自动配置,通过@SpringBootApplication 注解找到项目资源,spring.factories,通过扫描spring.factories里面的xxxAutoConfiguration 通过@Conditional派生注解判断配置类是否生效,如果生效,给容器中添加组件,这些组件的属性是从对应的properties类中获取的,可以根据配置文件(yaml或者property)设置值.
SpringApplication.run()