Spring Boot 2 基础入门
# 1. Spring 与 Spring Boot
# 1.1 Spring 能做什么?
# 1.1.1 Spring 生态
覆盖了:web开发、数据访问、安全控制、分布式、消息服务、移动开发和批处理。
# 1.1.2 Spring 5 重大升级
- 响应式编程
- 内部源码设计
基于 Java 8 的一些新特性,如:接口默认实现。重新设计源码架构。
# 1.2 为什么用 Spring Boot
# 1.2.1 优点
创建独立 Spring 应用;内嵌 web 服务器;自动 starter 依赖,简化构建配置;自动配置 Spring 以及第三方功能;提供生产级别的监控、健康检查及外部化配置;无代码生成,无需编写 XML
Spring Boot 是整合 Spring 技术栈的一站式框架,是简化 Spring 技术栈的快速开发脚手架
# 1.2.2 缺点
迭代快、封装太深、内部原理复杂
# 1.3 时代背景
# 1.3.1 微服务
James Lewis and Martin Fowler (2014) 提出微服务完整概念:https://martinfowler.com/microservices/
# 1.3.2 分布式
分布式的困难:RPC、服务发现、负载均衡、服务容错、配置管理、服务监控、链路追踪、日志管理、任务调度 ….
解决方案:Spring Boot + Spring Cloud
# 1.3.3 云原生(Cloud Native)
关键是原生应用如何上云的问题。
上云的困难:服务自愈、弹性伸缩、服务隔离、自动化部署、灰度发布、流量治理 …
上云的解决:
# 1.4 如何学习 Spring Boot
# 1.4.1 官网文档架构
Spring 官方文档:spring.io
# 2. Spring Boot 2 入门
用 Spring Boot 运行 Hello World.
# 3. 了解自动配置管理
# 3.1 依赖管理与自动配置
# 3.1.1 依赖管理
父项目做依赖管理,声明了很多开发中常用的 jar 包的依赖,使得我们不再用写版本号。
开发导入 starter 场景启动器:要引入 starter,这个场景的所有常规需要的依赖都会自动引入
无需关注版本号,自动版本仲裁:
- 引入依赖默认都可以不写版本
- 引入非版本仲裁的 jar,要写版本号
可以修改默认版本号:
- 查看 spring-boot-dependencies 里面规定当前依赖的版本
- 在当前项目里面重写配置:
<properties> <mysql.version>5.1.43</mysql.version> </properties>
1
2
3
# 3.1.2 自动配置
- 自动配好 Tomcat
- 自动配好 Spring MVC 全套组件
- 自动配好 Web 常见功能
- 默认的包结构:主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来,当然也可以通过注解来改变扫描路径。
- 各种配置拥有默认值
- 按需加载所有自动配置项:引入了哪些场景,这个场景的自动配置才会开启
# 3.2 容器功能
# 3.2.1 组件添加
# 1)@Configuration
- 告诉 Spring Boot 这是一个配置类 == 以前的 xml 配置文件
- 配置类本身也是 component
@Configuration(proxyBeanMethods = true)
的 proxyBeanMethods 为 true 时是 Full 模式,保证每个 @Bean 方法被直接调用多少次返回的组件都是单实例;为 false 时是 Lite 模式,每次被直接调用就是返回新实例。Best Practice:配置组件之间无依赖关系时用 Lite 模式来加速容器启动过程,而有依赖关系时,用 Full 模式来使得方法被调用时都是得到的之前的单例。
比如 @Bean 方法的
getCat
返回了一个 Cat,而另一个 @BeangetUser
返回了一个 User,而这个方法中直接调用了getCat
方法,这样就是组件之间有依赖关系,因此需要开启 Full 模式。
# 2)@Bean
给容器添加 component,以方法名作为组件的 id,返回类型就是组件的类型,返回的值就是组件在容器中的实例。默认是单实例的。
# 3)@Component、@Controller、@Service、@Repository
# 4)@ComponentScan
# 5)@Import
@Import({User.class, DBHelper.class})
@Configuration
public class MyConfig {
}
2
3
4
@Import
给容器中通过无参构造器自动创建出这两个类型的组件,默认组件的名字就是全类名(com.example.xxx.User)。
# 6)@Conditional
条件装配:满足 Conditional 指定的条件,则进行组件注入。这个注解还派生了很多其他类型的注解,分别代表了在满足 xxx 情况下进行注入。
# 3.2.2 原生配置文件引入:@ImportResource
当仍然有些情况需要用 xml 来配置时(比如老项目的迁移),直接在 Spring Boot 中写 beans.xml 是配置不进去的,这个时候需要用 @ImportResource 来将 xml 配置文件加载进去。
# 3.2.3 配置绑定
如何使用 Java 读取到 properties 文件中的内容,并且把它封装到 JavaBean 中,以供随时使用?
# 1)@ConfigurationProperties
/**
* 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
*/
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
...
}
2
3
4
5
6
7
8
9
10
11
这会读取 properties 配置文件并将 myCar.brand
和 myCar.price
用于创建此 component。
这个属性在 Spring Boot 也是经常使用。
# 2)@EnableConfigurationProperties + @ConfigurationProperties
@ConfigurationProperties
是说将配置绑定到一个类上,但并没有说注入 IOC 容器中,上面的例子是通过 @Component
实现的注入容器中,但如果这是个第三方的类而它没有用 @Component 呢?那就要用 @EnableConfigurationProperties 了:
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
...
}
@Configuration
@EnableConfigurationProperties(Car.class)
// 1、开启Car配置绑定功能
// 2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3.3 自动配置原理入门
# 3.3.1 引导加载配置类
@SpringBootApplication 是由下面三个注解组成的:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}
2
3
4
5
# 1)@SpringBootConfiguration
它就是一个 @Configuration,代表我们这个 Main 程序也是 Spring Boot 的一个配置类。
# 2)@ComponentScan
指定扫描哪些包,可参照 Spring 注解来学习其用法,在这里不再展开。
# 3)@EnableAutoConfiguration ⭐️
最重要的一个注解。除去元注解外,主要由 @AutoConfigurationPackage 和 @Import(AutoConfigurationImportSelector.class) 组成:
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
2
3
我们分别看一下。
# 4)@AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
2
- @Import 用于给容器中导入一个组件,导入了一个 Register,它可以将一个指定的包下的所有组件批量导入容器中。导入了哪些组件?是 Main 程序所在的包下的所有组件。
# 5)@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 位置的文件
# 3.3.2 按需开启自动配置项
虽然上百个场景的所有自动配置启动的时候默认全部加载,xxxAutoConfigration 按照条件装配规则(@Conditional),最终会按需配置。
# 3.3.3 修改默认配置
// TODO 这部分太难了
# 3.3.4 Best Practice
- 开发某个东西,先看看有没有它的场景依赖,并引入场景依赖,比如各种 starter
- 查看自动配置了哪些(选做)
- 自己分析,引入场景对应的自动配置一般都生效了
- properties 配置文件中
debug=true
开启自动配置报告
- 是否需要修改
- 参照文档 (opens new window)修改配置项
- 自定义加入或者替换组件:@Bean 或 @Component 等
- 自定义器:XXXCustomizer
# 4. 开发小技巧
# 4.1 Lombok
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2
3
4
IDEA 中安装 lombok 插件
# 4.2 dev-tools
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
2
3
4
5
项目或者页面修改以后:Ctrl+F9
# 4.3 Spring Initailizr
自动创建项目