企业开发基础-6-SpringBoot2--基础篇
基础入门
Spring
- Web 开发
- 数据访问
- 安全控制
- 分布式
- 消息服务
- 移动开发
- 批处理
- …
Why Spring Boot
- 能够创建独立的 Spring 应用
- 内嵌 Web 服务器
- 自动 starter 依赖,简化构建配置
- 自动配置 Spring 以及第三方功能
- 提供生产级别的监控、健康检查及外部化配置
- 没有代码生成,不需要 XML 配置
- SpringBoot 是整合 Spring 技术栈的一站式框架
- SpringBoot 是简化 Spring 技术栈的快速开发脚手架
时代背景
微服务
微服务是一种架构风格,将一个应用拆分为一组小型服务,每个服务运行在自己的进程内,也就是可独立部署和升级,服务之间使用轻量级 HTTP 交互,服务围绕业务功能拆分,可以由全自动部署机制独立部署,去中心化,服务自治。服务可以使用不同的语言、不同的存储技术。
分布式困难
- 远程调用
- 服务发现
- 负载均衡
- 服务容错
- 配置管理
- 服务监控
- 链路追踪
- 日志管理
- 任务调度
- ……
分布式解决方案
SpringBoot + SpringCloud
云原生
Cloud Native
上云困难
- 服务自愈
- 弹性伸缩
- 服务隔离
- 自动化部署
- 灰度发布
- 流量治理
- ……
上云解决方案
- 初识云原生
- 深入 Docker-容器化技术
- 掌握星际级容器编排 Kubernetes
- DevOps—实战企业 CI/CD,构建企业云平台
- 新一代架构 Service Mesh 与 Serverless
快速入门
引入依赖
1 | <parent> |
编写启动类
1 |
|
编写控制器
1 |
|
打包部署
1 | <build> |
运行 clean 、package,把 helloworld 工程项目的打包成 jar 包,运行 java -jar boot-01-helloworld-1.0-SNAPSHOT.jar
,即可以运行helloworld工程项目。
依赖管理
父项目进行依赖管理
1 | 依赖管理 |
stater 场景启动器
见到很多
spring-boot-starter-*
:*
是某种场景只要引入 starter,这个场景的所有常规需要的依赖都自动引入
见到的
*-spring-boot-starter
: 第三方为我们提供的简化开发的场景启动器
所有场景启动器最底层的依赖
1 | <dependency> |
自动版本仲裁
- 引入依赖默认可不写版本号
- 引入非版本仲裁的依赖需要写版本号
修改默认版本号
1 | <properties> |
自动配置
自动配置 Tomcat
引入 Tomcat 依赖,配置它
1 | <dependency> |
自动配置 SpringMVC
- 引入 SpringMVC 全套组件
- 自动配好 SpringMVC 常用组件(功能)
自动配置 Web 常见功能
Spring Boot 帮我们配置好了所有 web 开发的常见场景
1 |
|
默认包结构
- 主程序所在包及其下面的所有子包 里面的组件都会被默认扫描进来,无需以前的包扫描配置
- 想要改变扫描路径
@SpringBootApplication(scanBasePackages="com.cyan")
@ComponentScan
指定扫描路径
1 |
|
各种配置拥有默认值
- 默认配置最终都是映射到某个类上,如:
MultipartProperties
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
按需加载所有自动配置项
非常多的 starter,引入了哪些场景这个场景的自动配置才会开启,SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
底层注解
@Configuration
@Configuration
:配置类,取代配置文件,配置类本身是组件
属性 | 说明 |
---|---|
proxyBeanMethods |
代理Bean的方法 |
@Configuration(proxyBeanMethods = true) |
外部无论对配置类的组件注册方法调用多少次,获取的都是之前容器中注册的单实例对象,每次启动SpringBoot检查方法返回的对象在容器中有没有 |
@Configuration(proxyBeanMethods = false) |
不会检查方法返回的对象在容器中有没有,SpringBoot启动运行比较快 |
@Configuration(proxyBeanMethods = true)
MyConfig 是被 SpringCGLIB 增强了的代理对象,获取的本身就是代理对象
1 |
|
1 |
|
如果 @Configuration(proxyBeanMethods = true),该类获取到的是代理对象调用方法。SpringBoot 总会检查这个组件是否在容器中有没有该方法以及返回的组件,如果容器中有,直接拿;如果没有,再来调用、创建
1 |
|
总结:保持组件单实例
@Configuration(proxyBeanMethods = false)
1 |
|
1 |
|
类组件依赖
1 |
|
1 |
|
如果 @Configuration(proxyBeanMethods = true)
结果返回true,如果 @Configuration(proxyBeanMethods = false)
返回false
两种模式
Full
[ @Configuration(proxyBeanMethods = true) ]模式Lite
[ @Configuration(proxyBeanMethods = false) ]模式
- 配置 类组件之间 无依赖关系 用 Lite 模式加速容器启动过程,减少判断
- 配置 类组件之间 有依赖关系,方法会被调用得到之前单实例组件,用Full模式 (默认)
- 应用场景:解决组件依赖
@Bean
- 给容器中添加组件,以方法名作为组件的 id。返回类型为组件类型。返回值是组件在容器中的实例
- 自定义组件名:
@Bean("name")
- 配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
@Import
注解 | 说明 |
---|---|
@Import({User.class, DBHelper.class}) |
给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名 |
1 |
|
1 |
|
控制台输出
com.cyan.boot.entity.User
fun1(之前注入的)
ch.qos.logback.core.db.DBHelper@1929425f
@Conditional
注解 | 说明 |
---|---|
@Conditional | 条件装配:满足Conditional指定的条件,则进行组件注入 |
ConditionalOnBean
当容器中存在Tom组件fun1才生效,用于方法和类上同理
1 |
|
1 | // false |
@ImportResource
注解 | 说明 |
---|---|
@ImportResource | 导入Spring配置文件 |
application-context.xml
1 |
|
config
1 |
|
1 | boolean u1 = run.containsBean("u1"); |
@ConfigurationProperties
读取 properties 文件
使用 Java 读取到 properties 文件中的内容,并且把它封装到 JavaBean 中,以供随时使用
传统方式
1 | Properties properties = new Properties(); |
SpringBoot 配置绑定1
@ConfigurationProperties
+@Component
1 | mycar.brand=BYD |
1 |
|
1 |
|
只有在容器中的组件,才会拥有 SpringBoot 提供的强大功能
SpringBoot 配置绑定2
@EnableConfigurationProperties
+@ConfigurationProperties
只能在配置类里面写
- 开启Car配置绑定功能
- 把这个Car这个组件自动注册到容器中
1 |
|
1 |
|
自动配置原理
自动包规则原理
@SpringBootApplication
1 |
|
@SpringBootConfiguration
1 |
|
当前是一个配置类
@ComponentScan
1 |
|
指定扫描哪些Spring注解
@EnableAutoConfiguration
1 |
|
@AutoConfigurationPackage 自动配置包,指定了默认的包规则。
1 |
|
@AutoConfigurationPackage 原理总结
- 利用
Registrar
给容器中导入一系列组件 - 将指定的一个包下的所有组件导入进
MainApplication
所在包下。
初始加载自动配置类
@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector
getAutoConfigurationEntry(annotationMetadata); // 给容器中批量导入一些组件
1 | public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, |
getAutoConfigurationEntry
List
configurations = getCandidateConfigurations(annotationMetadata, attributes); // 获取到所有需要导入到容器中的配置类
1 | protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { |
getCandidateConfigurations
1 | protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { |
loadFactoryNames
利用工厂加载
Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);
得到所有的组件
1 | public static List<String> loadFactoryNames(Class<?> factoryType, { ClassLoader classLoader) |
loadSpringFactories
1 | private static Map<String, List<String>> loadSpringFactories( { ClassLoader classLoader) |
从META-INF/spring.factories
位置来加载一个文件。默认扫描我们当前系统里面所有META-INF/spring.factories
位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar
包里面也有META-INF/spring.factories
文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
1 | # Auto Configure |
按需加载配置
虽然我们127个场景的所有自动配置启动的时候默认全部加载,但是xxxxAutoConfiguration
按照条件装配规则(@Conditional
),最终会按需配置。
1 |
|
@Import(AutoConfigurationImportSelector.class) 原理总结
- 利用
getAutoConfigurationEntry(annotationMetadata);
给容器中批量导入一些组件 - 调用
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)
获取到所有需要导入到容器中的配置类 - 利用工厂加载
Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);
得到所有的组件 - 从
META-INF/spring.factories
位置来加载一个文件。- 默认扫描我们当前系统里面所有
META-INF/spring.factories
位置的文件 spring-boot-autoconfigure-2.3.4.RELEASE.jar
包里面也有META-INF/spring.factories
- 默认扫描我们当前系统里面所有
自动配置流程
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
文件上传解析器案例
Detect if the user has created a MultipartResolver but named it incorrectly
1 |
|
自动配置流程总结
- SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
- 生效的配置类就会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能生效了
个性化定制配置
- 用户直接自己
@Bean
替换底层的组件 - 用户去看这个组件是获取的配置文件什么值就去修改
HttpEncodingAutoConfiguration
1 |
|
ServerProperties
1 |
|
xxxxxAutoConfiguration —-> 组件 —-> xxxxProperties里面拿值 ——> application.properties
xxxAutoConfiguration 中导入了很多的组件,然后这些组件从 xxxProperties 中拿到对应的默认值,然后 xxxProperties 是从 application.properties 配置文件中获取的值,所以一般情况下我们只要改配置文件,就可以修改所有的默认行为。
配置文件
yaml
yml 的优先级会大于 properties,所以如果同时存在这两种配置,因为 properties 是后加载的,所以此时 yml 就没有生效
基本语法
key: value
;kv之间有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- ‘#‘表示注释
- 字符串无需加引号,如果要加,
''
与""
表示字符串内容 会被 转义/不转义
注:
单引号:会将\n
作为字符串输出
双引号:会将\n
作为换行输出
单引号会转义,双引号不会转义
数据类型
数据类型 | 说明 |
---|---|
字面量 | 单个的、不可再分的值。date、boolean、string、number、null |
对象 | 键值对的集合。map、hash、set、object |
数组 | 一组按次序排列的值。array、list、queue |
1 | # 字面量 |
案例分析
1 |
|
1 | person: |
1 |
|
1 | { |
自定义类绑定的配置提示
You can easily generate your own configuration metadata file from items annotated with
@ConfigurationProperties
by using thespring-boot-configuration-processor
jar. The jar includes a Java annotation processor which is invoked as your project is compiled.——link
自定义的类和配置文件绑定一般没有提示。若要提示,添加如下依赖:
1 | <dependency> |