SpringBoot基础
什么是Spring
Spring是一个开源框架,2003年兴起的一个Java轻量级开发框架,作者:Rod Johnson。
Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。
Spring是如何简化Java开发的
为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
- 基于POJO的轻量级和最小侵入性编程;
- 通过ICO,依赖注入(DI)和面向接口编程实现松耦合;
- 基于切面(AOP)和惯例进行声明式编程;
- 通过切面和模板减少样式代码
什么是SpringBoot
- Spring就是一个javaweb的开发框架,和SpringMVC类似,对比其他Javaweb的好处,官方说是简化开发,约定大于配置,you can “just run”,能迅速开发的web应用,几行代码开发一个http接口
- SpringBoot的主要优点:
- 为所有Spring开发者更快速的入门
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌式容器简化Web项目
- 没有冗余代码生成和XML配置的要求
微服务
-
什么是微服务
微服务是一种架构风格,它要求我们在开发应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通。
-
单体应用架构
- 所谓单体应用架构(all in one)是指我们将一个应用中的所有应用服务都封装在一个应用服务中
- 无论是CRM、ERP或是其他什么系统,你都把数据库访问、web访问等等各种功能都放到一个war包内
- 这样做的好处是易于开发和测试,也十分方便部署;当需要拓展是,只需将war复制多份,然后放到多个服务器上,再做一个负载均衡就可以了
- 单体架构的缺点是,哪怕我需要改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型项目,我们不可能把所有应用都放在一个应用里面,这样我们如何维护、如何分工合作都是问题
微服务架构
- all in one 架构方式,我把所有功能单元都放在一个应用里面,然后我们把整个应用都部署在服务器上。如果负载能力不行,我们把整个应用进行水平复制、进行拓展,然后再负载均衡
- 所谓微服务架构就是打破之前all in one的架构风格,把每个功能元素独立出来。把独立出来的功能元素动态组合,需要的功能元素才拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制
- 这样做的好处:
- 节省了调用资源
- 每个功能元素的服务都是一个可替换的、可独立升级的软件代码
如何构建微服务
-
一个大型系统的微服务架构,就像是一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http互相请求调用。比如一个电商系统,查缓存、查数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,它们作为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新其中一个功能服务单元即可
-
但是这种庞大的架构给部署和运维带来了很大的难度。于是Spring为我们带来了构建大型分布式微服务的全套产品:
- 构建一个个功能独立的微服务应用单元,可以使用SpringBoot,可以帮我们快速构建一个应用
- 大型分布式网络服务的调用,这部分由SpringCloud来完成,实现分布式
- 在分布式中间,进行流式数据计算、批处理,我们有SpringCloudDataFlow
- Spring为我们想清楚了从开始构建应用到大型分布式应用的全流程方案
-
微服务:
原文是 Martin Fowler 于 2014 年 3 月 25 日写的《Microservices》,翻译链接:
https://www.kuangstudy.com/bbs/1374644434515275777
自动装配原理
-
自动配置:pom.xml
spring-boot-dependencies:核心在父工程中
-
我们在写或者引入一些SpringBoot依赖的时候,不需要制定版本就是因为有这些版本仓库
-
启动器
- 启动器:说白了,就是SpringBoot的使用场景
- 比如说,spring-boot-starter-web,它就会自动帮我们导入web环境下所有的依赖
- SpringBoot会将所有的功能场景,变成一个个的启动器
- 我们要使用什么功能,只需要找到对应的启动器就可以了
<!--启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
-
主程序
-
代码
//@SpringBootApplication:标注这个类是一个SpringBoot的应用 @SpringBootApplication public class HelloApplication { //将SpringBoot应用启动 public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } }
-
注解解析:
@SpringBootConfiguration:SpringBoot的配置 @Configuration:Spring配置类 @Component:说明这也是一个Spring的组件 @EnableAutoConfiguration:自动配置 @AutoConfigurationPackage:自动配置包 @Import({AutoConfigurationPackage.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:自动配置的核心文件
-
总结
SpringBoot中所有的自动配置都在启动类中被扫描并加载,spring.factories:所有的自动配置类都在这里了,但不一定生效,要判断条件是否满足,只要导入了对应的start,就有对应的启动器了,有了启动器我们的自动装配就会生效,然后就配置成功了
1)SpringBoot在启动的时候,从类路径下/META-INF/spring.factories获取指定的值
2)将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置
3)以前我们需要自动配置的东西,现在SpringBoot帮我们做了
4)整个Java EE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.6.4.jar这个包下
5)它会把所有需要导入的组件以类名方式返回,这些组件就会被添加到容器
6)容器中也会存在很多的XXXAutoConfiguration的文件(@Bean:组件),就是这些类给容器中导入了这个场景所需要的所有组件;并自动配置,@Configuration(配置),javaConfig!
7)有了自动配置类,就免去了我们手动编写配置文件的工作
-
关于SpringBoot谈谈你的理解:
-
自动装配
-
run()
1.推断应用的类型是普通的项目还是Web项目
2.查找并加载所有可用初始化器,设置到initializers属性中
3.找出所有的应用程序监听器,设置到listeners属性中
4.推断并设置main方法的定义类,找到运行的主类
-
yaml语法详解
配置文件
SpringBoot使用一个全局的配置文件,配置文件名称是固定的
application.properties
○ 语法结构: key=value
# SpringBoot这个配置文件到底有哪些东西呢?
#
# 官方的配置太多了
#
# 了解原理:一通百通
# 将其删除,创建application.yaml文件,因为properties只能保存键值对
name=xiaoShu
student.name=xiaoShu
student.age=3
application.yml
○ 语法结构:key:空格 value
# k=v
#对空格的要求十分高!
#普通的key-value
# 可以注入到配置类中!
name: xiaoShu
# 对象
student:
name: xiaoShu
age: 3
# 行内写法
# student: {name: xiaoShu,age: 3}
# 数组
pets:
- dog
- cat
- pig
# pets: [dog,cat,pig]
配置文件的作用∶修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;
YAML
YAML是"YAML Ain’t a Markup Language"(YAML不是一种置标语言)的递归缩写。
在开发的这种语言时,YAML的意思其实是:“Yet Another Markup Language”(仍是一种置标语言)
YAML A Markup Language:是一个标记语言
YAML is not Markup Language:不是一个标记语言
标记语言
以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml
yaml配置:
- yaml可以直接给实体类赋值
server:
port: 8080
xml配置:
<server>
<port>8080<server>
</server>
功能对比图:
-
cp只需要配置一次即可,@value()则需要每个字段都添加
-
松散绑定:这个是什么意思呢?比如我的yaml中写的last-name,这个和lastName是一样的,-后面跟着的字母默认是大写的。这就是松散绑定。
-
JSR303数据校验:这个就是我们为字段增加一层过滤器验证,保证我们数据的合法性
SpringBoot中可以使用@validated来校验数据,如果数据异常就会统一抛出异常,方便异常中心统一处理。这里我们来写个注解让我们的name只支持email格式
@Component //表示Spring的组件:实体类,注册Bean @ConfigurationProperties(prefix = "dog") @Validated //数据校验 public class Dog { //@Value("旺财") //给属性赋值 @Email //name必须是邮箱格式 private String name; @Value("#{11*2}") //#{SPEL} Spring表达式 private Integer age;
-
复杂类型封装:yaml可以支持封装数据对象,@value就不支持
结论:
- 配置yaml和properties都可以获取到值,一般使用yaml
- 如果我们在业务中,只需要获取配置文件中的某个值可以使用一下@value
- 如果说,我们专门编写了一个JavaBean来和配置文件进行映射,就直接使用@ConfigurationProperties(prefix = “XXX”),不要犹豫!
SpringBoot的多环境配置,可以选择激活哪一个
application.properties配置:
application.yaml配置:
自动配置原理总结:
一句话总结:根据当前不同的条件判断,决定这个配置类是否生效
一旦这个配置类生效,这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类的
每一个属性又是和配置文件绑定的
这就是自动装配的原理!精髓:
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
xxxAutoConfigurartion:自动配置类;给容器中添加组件xxxxProperties:封装配置文件中相关属性;
#可以通过debug: true来查看哪些自动配置类生效了,哪些没有生效
debug: true