尚硅谷SpringBoot2核心技术-基础入门(一)
spring与springboot
spring能做什么?
spring的能力
- 微服务开发
- 响应式编程
- 分布式云开发
- web开发
- 无服务开发(函数式服务)
- 事件驱动
- 批处理业务
spring的生态
spring的生态覆盖了一下内容
- web开发
- 数据访问
- 安全控制
- 分布式
- 消息服务
- 移动开发
- 批处理
- …..
spring5的重大升级
响应式编程
内部源码设计
基于Java8的一些新特性,如:接口默认实现,重新设计源码架构
为什么使用SpringBoot
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.
能快速创建出生产级别的Spring应用
SpringBoot优点
- Create stand-alone Spring applications
- 创建独立Spring应用
- Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
- 内嵌web服务器
- Provide opinionated ‘starter’ dependencies to simplify your build configuration
- 自动starter依赖,简化构建配置
- Automatically configure Spring and 3rd party libraries whenever possible
- 自动配置spring以及第三方功能
- Provide production-ready features such as metrics, health checks, and externalized configuration
- 提供生产级别的监控、健康检查及外部化配置
- Absolutely no code generation and no requirement for XML configuration
- 无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
SpringBoot缺点
- 人称版本帝,迭代快,需要时刻关注变化
- 封装太深,内部原理复杂,不容易精通
时代背景
微服务
- 微服务是一种架构风格
- 一个应用拆分为一组小型服务
- 每个服务运行在自己的进程内,也就是可独立部署和升级
- 服务之间使用轻量级HTTP交互
- 服务围绕业务功能拆分
- 可以由全自动部署机制独立部署
- 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术
分布式
分布式的困难
- 远程调用
- 服务发现
- 负载均衡
- 服务容错
- 配置管理
- 服务监控
- 链路追踪
- 日志管理
- 任务调度
- ……
分布式的解决
- SpringBoot + SpringCloud
云原生
原生应用如何上云。 Cloud Native
上云的困难
- 服务自愈
- 弹性伸缩
- 服务隔离
- 自动化部署
- 灰度发布
- 流量治理
- ……
如何学习SpringBoot
官网文档架构
Home · spring-projects/spring-boot Wiki · GitHub
SpringBoot2入门
创建maven工程
- 使用idea创建maven工程
引入依赖
1 | <parent> |
创建主程序
1 |
|
编写业务
1 |
|
测试
- 直接运行main方法
简化配置
- application.properties
1 | 8888 = |
简化部署
- 直接将项目打成可执行jar,放到对应服务器上运行即可
1 | <build> |
了解自动配置原理
SpringBoot特点
依赖管理
父项目做依赖管理
- 依赖管理
1 | <parent> |
- spring-boot-starter-parent 的父项目
1 | <parent> |
- dependencies中几乎声明了开发中所有常用的依赖的版本号,自动版本仲裁机制
开发导入starter场景启动器
- 有很多
spring-boot-starter-*
:*
就是某种场景 - 只要引入starter ,这个场景的所有常规需要的依赖就都会自动引入
- SpringBoot所有支持的场景:Developing with Spring Boot
- 见到的
*-spring-boot-starter
:第三方为我们提供的简化开发的场景启动器 - 所有场景启动器最底层的依赖
1 | <dependency> |
无需关注版本号,自动版本仲裁
- 引入的依赖默认都可以不写版本号
- 引入非版本仲裁的jar,需要些版本号
可以修改默认版本号
- 查看
spring-boot-dependencies
里面规定当前依赖的版本 用的key - 在当前项目里面重新配置
1 | <properties> |
- 也可以在引入依赖的时候直接指定版本,指定后会覆盖父项目所指定的版本
1 | <dependency> |
自动配置
- 自动配置Tomcat
- 引入Tomcat依赖
- 配置Tomcat
1 | <!-- spring-boot-starter-web中自动引入了tomcat的依赖 --> |
自动配置号SpringMVC
- 引入SpringMVC全套组件
- 自动配置好SpringMVC常用组件(功能)
自动配置号web常见功能,如:字符编码问题
- SpringBoot帮我们配置好了所有web开发的常见场景
默认的包结构
- 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
- 不需要再像以前一样在xml中进行包扫描路径配置
- 想要改变默认扫描路径:@SpringBootApplication(scanBasePackages = “com.ys”)
- 或者:@ComponentScan 指定扫描路径
1 |
|
各种配置拥有的默认值
- 默认配置最终都会映射到某一个配置类上
- 配置文件的值最终会绑定到配置类上,这个类会在容器中创建对象
按需加载所有自动配置项
- springboot提供了非常多的starter
- 引入了哪些场景,这个场景的自动配置才会开启(没有引入的配置不会开启)
- springboot所有的自动配置功能都在
spring-boot-autoconfigure
包里面
容器功能
组件添加
@Configuration
- 基本使用
- full模式和lite模式
- 最佳实践
- 配置类组件之间无依赖关系,用Lite模式加速容器启动过程,减少判断
- 配置类组件之间有依赖关系,方法会被条用得到之前单实例组件,用Full模式
1 | /** |
@Bean @Component @Controller @Service @Repository
- @Bean:标记在方法上,代表方法返回的是在一个组件
- @Component:标记在类上,表示这个类是一个组件
- @Controller:标记在类上,表示这个类是一个控制器
- @Service:表示这是一个业务逻辑组件
- @Repository:表示这是一个数据库层组件
@ComponentScan @Import
- @ComponentScan : 配置包扫描路径
- @Import:给容器中创建某种类型的组件,默认组件的名称就是全类名
1 |
@Conditional
- 条件装配:满足Conditional指定的条件,则进行组件注入
1 |
|
原生配置文件引入
@ImportResource
1 |
|
配置绑定
直接通过java的方式进行配置绑定:
需要去匹配配置文件中的key,很麻烦
1 | public class getProperties { |
@ConfigurationProperties
1 | BYD = |
当我们在配置文件中写了如上面的两行配置,只需要进行下面的代码配置,springboot就会帮我们自动绑定相关配置(@ConfigurationProperties
直接需要和 @Component
或者 @EnableConfigurationProperties
一起使用,只有在容器中的组件,才会拥有springboot提供的强大功能)
1 |
|
@EnableConfigurationProperties + @ConfigurationProperties
在配置类上标记@EnableConfigurationProperties
注解,并在注解中指定启用哪一个类的配置,一定要在配置类上标记(标记了@Configuration
注解的类)
1 |
|
@Component + @ConfigurationProperties
在配置类上面标记@Component
注解,表示将该类注册成一个组件
1 |
|
自动配置原理入门
引导加载自动配置类
查看SpringBootApplication注解的源码可以看到,这个注解是由三个注解组成的(已去除java注解定义必须的元注解)
1 |
|
@SpringBootConfiguration
@SpringBootConfiguration 注解的源码如下,它只是实现了一个 @Configuration 注解,表示被标记的类是一个配置类
1 |
|
@ComponentScan
@ComponentScan注解主要就是指定扫描包路径,springboot默认配置了一些过滤器,用来处理扫描路径
@EnableAutoConfiguration
EnableAutoConfiguration注解上面也是标注了两个注解
1 |
|
@AutoConfigurationPackage
自动配置包,指定了默认的包规则
1 | //使用 Import 注解给容器中导入一个组件 |
Registrar 类是一个静态内部类,里面一共有两个方法;
其中的第一个方法 registerBeanDefinitions 的第一个参数 AnnotationMetadata 元注解信息,这里的信息就是标注了 @SpringBootApplication 注解的类的信息,通过该注解获取到包路径信息,进行扫描。
1 | static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { |
@Import({AutoConfigurationImportSelector.class})
- 给容器中添加了
AutoConfigurationImportSelector
组件 - 会调用
AutoConfigurationImportSelector
中的selectImports
方法 selectImports
方法中会使用getAutoConfigurationEntry(annotationMetadata)
;给容器中导入一些组件- 在
getAutoConfigurationEntry
方法中,利用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取到所有需要导入到容器中的配置类 Map<String, List<String>> loadSpringFactories(ClassLoader classLoader);
加载所有组件- 读取一个文件
META-INF/spring.factories
- 默认扫描当前系统中所有的
META-INF/spring.factories
文件 spring-boot-autoconfigure-2.7.13.jar
包里面也有META-INF/spring.factories
- 默认扫描当前系统中所有的
注意:在springboot2.7开始,spring-boot-autoconfigure-2.7.13.jar
中自动配置的配置类已经不在META-INF/spring.factories
文件中了,而是转移到了/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件中,
目前截至到 2.7.13 版本 一共是是144个配置类
按需开启自动配置项
- 虽然我们144个场景的所有自动配置启动的时候默认全部加载,
xxxxAutoConfiguration
- 按照条件装配规则(
@Conditional
)最终会按需配置
如下图可以做一个简单的解析@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
这一行配置表示要去判断spring.aop.auto
这个配置项的值是否配置的true,matchIfMissing = true
则表示如果没有进行配置也自动开启,意思就是默认开启,出除非配置了关闭才会关闭AspectJAutoProxyingConfiguration
内部静态类,上面的@Configuration
表示这以上一个配置类,@ConditionalOnClass(Advice.class)
注解表示当Advice
这个类存在的时候才会生效,从图中可以看到该类为红色,所以目前是不生效的。
下面的ClassProxyingConfiguration
内部静态类同样是一个配置类,@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
注解表示Advice
这个类不存在的时候才会生效,而下面的@ConditionalOnProperty
注解表示spring.aop.proxy-target-class
这个类为true才会生效,同样,如果没有配置也会生效,所以该静态内部类里面的bean会生效。
修改默认配置
1 |
|
springboot会在底层配置好所有必须的bean,但如果用户也进行了配置,那么以用户配置的优先
1 |
|
总结:
- SpringBoot先加载所有的自动配置类,
xxxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件类,类中会设置一些默认值,也可以通过配置文件进行修改。
xxxProperties
- 生效的配置类就会给容器中装配很多bean
- 只要容器中有这些bean,就相当于这些功能都有了
- 定制化配置
- 用户直接自己用
@Bean
自定义bean替换底层的bean - 用户去看这个bean获取的配置文件是什么值进行修改,或者从官网文档看。
- 用户直接自己用
Common Application Properties (spring.io)
xxxAutoConfiguration
—> 组件 —> xxxProperties
里面取值 —> application.properties
最佳实践
- 引入场景依赖
- 查看自动配置了哪些(选做)
- 自己分析,引入场景的自动配置一般都会生效
- 配置文件中添加
dubug=true
开启自动配置报告。Positive matches:
表示已经生效的自动配置Negative matches:
表示没有生效的自动配置
- 是都需要修改
- 参照文档修改配置项
- Common Application Properties (spring.io)
- 自己分析,
xxxProperties
绑定了配置文件的哪些。
- 自定义加入还或者替换组件
+@Bean
、@Component
…. - 自定义器
xxxCustomizer
- …
- 参照文档修改配置项
开发小技巧
Lombok
简化开发,使用注解的方式在编译代码的时候自动生成getter、setter、有参构造、无参构造等方法
1 | <dependency> |
dev-tools
热部署,修改了代码之后不需要再重启项目,可以自动重新加载(自动重启项目,并不是真正的热加载)。
1 | <dependency> |
Spring Initailizr(项目初始化)
- 选择我们需要的开发场景
- 自动依赖引入
- 自动创建项目结构
- 自动编写好主配置类
也可以使用在线方式:
spring:Spring Initializr
阿里云:Cloud Native App Initializer (aliyun.com)