什么是 Spring?
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。Spring是一个开源框架,它由Rod Johnson创建。
目的是为了解决企业应用开发的复杂性而创建的。
Spring 如何简化 Java 开发的?
为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
1、基于 POJO 的轻量级和最小侵入性编程;
2、通过 IOC,依赖注入(DI)和面向接口实现松耦合;
3、基于切面(AOP)和惯例进行声明式编程;
4、通过切面和模版减少样式代码;
什么是 SpringBoot?
SpringBoot是由Pivotal团队在2013年开始研发、2014年4月发布第一个版本的全新开源的轻量级框架。它基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。
其设计目的是用来简化新Spring应用的初始搭建以及开发过程。
SpringBoot框架中还有两个非常重要的策略:开箱即用和约定优于配置。
特征:
- 可以创建独立的Spring应用程序
- 内嵌Tomcat,Jetty或Undertow(无需部署WAR文件)
- 提供自动配置的 “starter” 项目对象模型(POMS)以简化Maven配置
- 尽可能自动配置 Spring 和第三方库
- 提供准备好的特性,如指标、健康检查和外部化配置
- 完全没有代码生成,也不需要XML配置
什么是微服务?(以后再学)
https://www.zhihu.com/question/65502802
一、SpringBoot 项目创建
官网创建:https://start.spring.io/
IDEA 创建:
pom.xml中的配置:
- parent: 继承
spring-boot-starter-parent
的依赖管理,控制版本与打包等内容 - dependencies: 项目具体依赖,这里包含了
spring-boot-starter-web
用于实现HTTP接口(该依赖中包含了Spring MVC),官网对它的描述是:使用 Spring MVC 构建Web(包括RESTful)应用程序的入门者,使用Tomcat作为默认嵌入式容器。spring -boot-starter-test
用于编写单元测试的依赖包。更多功能模块的使用我们将在后面逐步展开。
- build:构建配置部分。默认使用了
spring-boot-maven-plugin
,配合spring-boot-starter-parent
就可以把 Spring Boot 应用打包成 JAR 来直接运行。
测试
在主程序即 xxxApplication 同级目录下新建一个包 controller【一定要在同级目录下,否则识别不到】。
编写代码:
@RestController
public class HelloController {
// 接口: http://localhost:8080/hello/
@RequestMapping("/hello")
public String hello(){
// 调用业务,接收前端参数
return "Hello SpringBoot!";
}
}
启动主程序,并在浏览器中输入:http://localhost:8080/hello/ 测试。
彩蛋
在 resources 目录下新建 banner.txt
再去 bootschool 找ASCII艺术字(图)集写到 banner.txt
就可以修改 SpringBoot 的启动图标了
二、 原理初探
1、 SpringBoot 自动装配原理:
pom.xml
spring-boot-dependencies
: 核心依赖在父工程中- 我们在写或者引入一些 SpringBoot 依赖的时候,不需要指定版本,就是因为有这些版本仓库。
启动器 :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
- 说白了就是 SpringBoot 的启动场景。
- 比如
<artifactId>spring-boot-starter-web</artifactId>
: 就会帮我们自动导入 web 环境所有的依赖。 - SpringBoot 会将所有的功能场景,都变成一个个的启动器。
- 如果我们要使用什么功能,就只需要找到对应的启动器就可以了。 “starter”
主程序
// @SpringBootApplication: 标注这个类是一个 SpringBoot 的应用。
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
// 将 SpringBoot 启动
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
- 注解(Ctrl + 鼠标左键 点入)
>自行查阅<
注解的用途
原文链接:https://blog.csdn.net/yuzongtao/article/details/83306182
在看注解的用途之前,有必要简单的介绍下XML和注解区别,
- 注解:是一种分散式的元数据,与源代码紧绑定。
- xml:是一种集中式的元数据,与源代码无绑定
当然网上存在各种XML与注解的辩论哪个更好,这里不作评论和介绍,主要介绍一下注解的主要用途:
- 生成文档,通过代码里标识的元数据生成javadoc文档。
- 编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证。
- 编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码。
- 运行时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例。
@Import
@Import
注解功能就是和Spring XML 里面 的 一样. @Import注解是用来导入配置类或者一些需要前置加载的类.
@Configuration
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被 AnnotationConfigApplicationContext
或 AnnotationConfigWebApplicationContext
类进行扫描,并用于构建bean定义,初始化Spring容器。
@SpringBootApplication
: 组合注解@SpringBootConfiguration
: SpringBoot 的配置@Configuration
@Component
: 说明这也是一个 Spring 的组件
@EnableAutoConfiguration
: 自动配置@AutoConfigurationPackage
: 自动配置包@Import(AutoConfigurationPackages.Registrar.class)
: 自动配置包注册
@Import(AutoConfigurationImportSelector.class)
: 自动配置导入选择
@ComponentScan
: 扫描当前主启动类同级的包
自动配置导入选择 : AutoConfigurationImportSelector
类下的 selectImports()
方法调用的 getAutoConfigurationEntry()
方法中:
// 获取所有的配置。
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
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 : 自动配置的核心文件
自动配置真正实现是从 classpath
中搜寻所有的 META-INF/spring.factories
配置文件,并将其中对应的 org.springframework.boot.autoconfigure
.包下的配置项,通过反射实例化为对应标注了 @Configuration
的 JavaConfig 形式的IOC容器配置类,然后将这些都汇总成为一个实例并加载到IOC容器中。
结论:
springboot 所有自动配置都是在启动的时候扫描并加载: spring.factories 所有的自动配置类都在这里面,但是不一定生效:要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!
- SpringBoot在启动的时候从类路径下的 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的值
- 将这些值作为自动配置类导入容器,自动配置类就生效,帮我们进行自动配置工作;
- 以前我们需要自己配置的东西,自动配置类都帮我们解决了
- 整个J2EE的整体解决方案和自动配置都在 springboot-autoconfigure.jar 包中;
- 它将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中;
- 它会给容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件. @Configuration > JavaConfig!
- 有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;
2、 主启动类运行
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
// 该方法返回一个 configurableApplicationContext 对象
// 参数一:应用入口的类 参数二:命令行参数
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
SpringApplication.run 分析分为两部分:一是 SpringApplication 实例化,二是 run 方法执行。
SpringApplication
这个类主要做了以下四件事情
- 推断应用的类型是普通的项目还是Web项目
- 查找并加载所有可用初始化器,设置到 initializers 属性中
- 找出所有的应用程序监听器,设置到 listeners 属性中
- 推断并设置 main 方法的定义类,找到运行的主类
三、 yaml 语法
配置文件
SpringBoot 使用一个全局配置文件,配置文件名称是固定的
- application.properties
- 语法结构 : key=value
- application.yaml
- 语法结构: key: 空格 value
配置文件的作用: 修改 SpringBoot 自动配置的默认值,因为 SpringBoot 在底层都给我们自动配置好了。
- 语法结构: key: 空格 value
yaml
YAML 是 “YAML Ain’t a Markup Language”(YAML 不是一种标记语言)的递归缩写。
在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。
标记语言:
- yaml 配置
server:
port: 8080
- xml 配置
<server>
<port>8080</port>
</server>
yaml 基本语法
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- '#'表示注释
1、 对象
# 对象
# 1. 对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格。
student:
name: 'mianbao'
age: 3
# 2. 也可以使用 key:{key1: value1, key2: value2, ...}。
student: {name: 'mianbao', age: 3}
2、 数组
# 数组
# 1. 以 - 开头的行表示构成一个数组
pets:
- cat
- dog
- pig
# 2. 可以使用行内表示:key: [value1, value2, ...]
pets: [cat, dog, pig]
3、 纯量
# 纯量
# 纯量是最基本的,不可再分的值,包括:字符串、布尔值、整数、浮点数、Null、时间、日期
boolean:
- TRUE #true,True都可以
- FALSE #false,False都可以
float:
- 3.14
- 6.8523015e+5 #可以使用科学计数法
int:
- 123
- 0b1010_0111_0100_1010_1110 #二进制表示
null:
nodeName: 'node'
parent: ~ #使用~表示null
string:
- 哈哈
- 'Hello world' #可以使用双引号或者单引号包裹特殊字符
- newline
newline2 #字符串可以拆成多行,每一行会被转化成一个空格
date:
- 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime:
- 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
四、给属性赋值的几种方式
yaml 可以直接给实体类赋值
Dog:
@Component
public class Dog {
private String name;
private Integer age;
// getter and setter
}
Person:
@Component
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
// getter and setter
}
// 实体类
@Component
public class Dog {
@Value("旺财")
private String name;
@Value("5")
private Integer age;
// getter and setter
}
// 测试类
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Dog dog;
@Test
void contextLoads() {
System.out.println(dog);
}
}
person:
name: miaobao
age: 3
happy: false
birth: 2020/11/23
maps: {k1: v1, k2: v2}
lists:
- code
- music
- girl
dog:
name: 旺财
age: 3
实体类使用注解:@ConfigurationProperties(prefix = “person”)
解决,引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
@ConfigurationProperties作用:
-
将配置文件中配置的每一个属性的值,映射到这个组件中;
-
告诉 springBoot 将本类中的所有属性和配置文件中相关的配置进行绑定
-
参数 prefix = “person”: 将配置文件中的 person 下面的所有属性—─对应
-
只有这个组件是容器中的组件,才能使用容器提供的 @ConfigurationProperties 功能
3. 使用 properties 文件
mianbao.properties
name=mianbao
Person 类:
@Component
// 加载指定的配置文件
@PropertySource(value = "classpath:mianbao.properties")
public class Person {
// 使用 SPEL 取出配置文件的值
@Value("${name}")
private String name;
..........
JavaConfig 绑定配置文件的值,可以采取以上方式!
- 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下@value
- 如果说,我们专门编写了一个JavaBean来和配置文件进行映射,就直接使用@configurationProperties!
yaml 配置随机值
它可以生成整数,长整数,uuids或字符串
person:
name: miaobao${random.uuid}
yaml 的松散绑定
这个什么意思呢?比如我的yml中写的last-name,这个和lastName是一样的,-后面跟着的字母默认是大写的。这就是松散绑定。
dog:
first-name: 阿黄
age: 3
@Component
@ConfigurationProperties(prefix = "dog")
public class Dog {
private String firstName;
private Integer age;
...
}
JSR-303数据校验
这个就是我们可以在字段是增加一层过滤器验证,可以保证数据的合法性复杂类型封装,yml中可以封装对象,使用@value就不支持。
需要带入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
类上面配置 @Validated 注解,需要校验的参数配置上对应的注解,当方法被调用的时候自动对参数校验,如果校验的结果不通过就抛出异常,会打印配置的message的内容。
@Component
@ConfigurationProperties(prefix = "person")
@Validated // 数据校验
public class Person {
@Email(message = "邮箱格式不正确")
private String name;
.....
}
校验规则:
五、配置文件位置和多环境配置
配置文件位置
SpringBoot版本: 2.4.0
测试时优先级:
- 根目录下的:/config/application.yaml
- 根目录下的:/application.yaml
- classpath: /config/application.yaml
- classpath: /application.yaml
server:
port: 808X # 8081 8082 8083 8084
官方文档的优先级???
- The classpath root
- The classpath /config package
- The current directory
- The /config subdirectory in the current directory
- Immediate child directories of the /config subdirectory
多环境配置
application.properties 通过以下配置激活(通过后缀):
# SpringBoot 多环境配置,可以选择激活哪一个配置文件
spring.profiles.active=test
yaml 格式的多环境配置
server:
port: 8081
spring:
profiles:
active: test
# dev 环境
--- # 分隔符
server:
port: 8082
spring:
profiles: dev
# test 环境
---
server:
port: 8083
spring:
profiles: test
七、 自动配置原理再理解
SpringBoot 配置文件到底能写什么<----联系----> META-INF/spring.factories(自动配置的核心文件)
META-INF/spring.factories 里面的org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration 点进去
// 标注这是一个配置类
@Configuration(proxyBeanMethods = false)
// 自动配置属性 : ServerProperties
@EnableConfigurationProperties(ServerProperties.class)
// ConditionalOnXXX : Spring 的底层注解,来判断当前配置或者类是否生效!
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
....
}
点进自动配置属性类:ServerProperties, 发现和配置文件里可以配置字段和类 ServerProperties
里属性 相符合。
xxxAutoConfiguration :自动装配从 xxxProperties类 中获取的默认值。
xxxProperties类 和 配置文件 绑定 ,我们就可以使用配置文件进行自定义配置了。
@EnableConfigurationProperties 注解
使用@ConditionalOnProperty
注解来控制@Configuration
是否生效.
例子:
@Configuration
@ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true")
public class FilterConfig {
...
}
配置文件中的代码
filter.loginFilter=true
配置类生效。
@Conditional 注解
- 标注在类上面,表示该类下面的所有
@Bean
都会启用配置 - 标注在方法上面,只是对该方法启用配置
@ConditionalOnXXX
自动配置类必须在一定条件下才能生效.
作用:必须是 @ConditionalOn
指定的条件成立,才能给容器中添加组件,配置里面的所有内容才会生效
这就是自动装配的原理!
1)、SpringBoot 启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有在 SpringBoot 默认写好的自动配置类当中;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
4)、给容器中自动配置类添加组件的时候,会从 properties类 中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
- xxxxAutoConfigurartion: 自动配置类: 给容器中添加组件
- xxxxProperties: 封装配置文件中相关属性
可以通过此配置,来查看哪些自动配置类生效,哪些自动配置类没有生效