SpringBoot-01-入门
1 SpringBoot入门
1.1 SpringBoot简介
什么是Spring?
- Spring是为了简化企业开发负责性而创建的一个框架
Spring如何简化Java开发的?
- 基于pojo的轻量级编程,实现了最小入侵,所有的东西都可以被Spring容器进行管理
- IoC和面向接口编程降低了各个组件之间的耦合性
- 通过 AOP 实现了业务功能的横向扩展
- 通过模板(Template)减少重复工作
SpringBoot是什么?
- SpringBoot 是类似于 SpringMVC 的一种 java web 框架
- SpringBoot 通过自动装配,减少了大量的Spring配置。因为使用了自动装配,所以SpringBoot 中约定大于配置
SpringBoot的优点
- 为所有 Spring 开发提供快速且广泛可访问的入门体验。
- 开箱即用,使用各种默认配置来简化项目配置
- 提供大型项目所共有的一系列非功能特性(如嵌入式服务器、security)
- 绝对没有代码生成,也不需要 XML 配置
1.2 Hello SpringBoot
-
新建一个IDEA项目,选择Spring Initiallizr
-
填好项目配置之后,记得在这里选上spring web的依赖
-
在Finish之后,idea会自动完成SpringBoot项目的创建。如果是第一次创建SpringBoot项目的话,需要下载相关依赖,这个要等待一会
-
随便写一个接口
-
Controller
@RestController public class HelloController { @RequestMapping("/hello") public String hello() { return "Hello SpringBoot"; } }
-
-
点击运行
-
可以看到,我只写了一个Controller来处理一个请求,没有做任何多余的工作,没有配置SpringMVC,没有配置web.xml 。。。。。。
-
这就是SpringBoot的强大之处,快速部署
彩蛋
-
在resources目录下,新建一个banner.txt文件,即可更改SpringBoot的启动界面
-
原界面
-
新界面
2 初看自动装配
2.1 pom.xml
-
SpringBoot的maven配置文件主要由这么几个部分组成
-
父项目依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.1</version> <relativePath/> <!-- lookup parent from repository --> </parent>
- 父项目里面有所有SpringBoot整合的依赖,我们如果需要添加其他支持,只需要从中引用对应的启动器即可
-
启动器
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
- SpringBoot将所有支持的场景都进行抽取,然后做成了一个个单独的启动器。
- SpringBoot中的所有启动器都已经配置好了必要的参数,以此实现 开箱即用
2.2 主启动类
-
代码
@SpringBootApplication public class Springboot01HellospringbootApplication { public static void main(String[] args) { SpringApplication.run(Springboot01HellospringbootApplication.class, args); } }
-
这就是所有SpringBoot应用程序的主入口,执行主启动类的main方法就可以启动SpringBoot
深入分析
@SpringBootApplication
-
进入源码查看
-
@ComponentScan
- ComponentScan这个我们都熟悉。在Spring中,我们通过配置这个属性来使得我们可以使用
@Component
等注解进行开发。由此可以推断这个注解的作用是扫描我们SpringBoot中的注解用的
- ComponentScan这个我们都熟悉。在Spring中,我们通过配置这个属性来使得我们可以使用
-
@SpringBootConfiguration
-
阅读注释
Indicates that a class provides Spring Boot application {@link Configuration @Configuration}. Can be used as an alternative to the Spring's standard {@code @Configuration} annotation so that configuration can be found automatically (for example in tests). <p> Application should only ever include <em>one</em> {@code @SpringBootConfiguration} and most idiomatic Spring Boot applications will inherit it from {@code @SpringBootApplication}. @author Phillip Webb @author Andy Wilkinson @since 1.4.0
-
通过注释,我们可以得知这个注解的作用就是告诉Spring,这个类是SpringBoot的应用程序,需要被扫描
-
-
@EnableAutoConfiguration
-
这个注解的作用是开启Spring的自动配置,尝试推导出你要使用哪些bean。同时可以用于指定不需要自动配置的类
-
同时引用了一个自动配置选择器的类
AutoConfigurationImportSelector
-
源码中的注释同时还提到了,所有自动配置的类,都是Spring中的bean,他们都用下面的三个注解进行标注
-
-
AutoConfigurationImportSelector
-
这个类的就是SpringBoot的自动装配的主力军,他的作用就是完成自动装配
-
getCandidateConfigurations()
用于获取需要配自动配置的类的名字,是完成自动装配的关键。比如说web项目的话,需要配置SpringMVC中的DispatcherServlet。/** * Return the auto-configuration class names that should be considered. By default * this method will load candidates using {@link SpringFactoriesLoader} with * {@link #getSpringFactoriesLoaderFactoryClass()}. * @param metadata the source metadata * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation * attributes} * @return a list of candidate configurations */ 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; }
-
-
SpringFactoriesLoader
- 这个类是Spring内部的工厂加载类,用来加载各种工厂的。需要被加载的工厂都以
properties
的格式存储在META-INF/spring.factories
文件中 - 得知这点,我们找到
AutoConfigurationImportSelector
所在的jar包,找到spring.factories
文件
- 这个类是Spring内部的工厂加载类,用来加载各种工厂的。需要被加载的工厂都以
-
spring-boot-autoconfigure-2.4.1
包中的spring.factories
- 找到这个文件之后,就一目了然了。原来实现自动装配的都是这些类。他们这些类都是Java配置类(Java配置类就是通过Java的代码配置Spring)
-
SpringBoot自动装配小结
2.3 SpringApplication
- SpringApplication这个类主要做了这么几个事情
- 推断应用类型,看看是不是WEB应用
- 查找并加载所有可用的初始化值,设置到initializers中
- 找出所有的应用程序监听器,设置到listeners属性中
- 加载main方法的定义类,找到运行的主类
3 配置SpringBoot
3.1 外部配置文件
-
SpringBoot在启动时自动到以下路径去搜索配置文件。其中,配置文件的名称都是统一的
application.xxx
classpath
,也就是resources
目录,这也是生成SpringBoot项目时默认的配置文件位置。classpath/config
,也就是resources/config
currentpath
,也就是当前项目所在的目录currentpath/config
,也就是项目根目录下的config
- 注意:这四个位置的配置文件优先级由低到高。SpringBoot会使用高优先级的配置文件
-
SpringBoot支持
properties
和yaml
两种格式的配置文件。其中,官方推荐我们使用yaml
3.2 YAML
什么是YAML
- YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。
- YAML 的语法和其他高级语言类似,并且可以简单表示变量、数组、map等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。
语法
-
大小写敏感
-
使用缩进表示层级关系,对于缩进非常严格(只允许使用空格缩进)
-
缩进的空格数不重要,只要相同层级的元素左对齐即可
-
变量,
key: value
,其中冒号后面必须跟一个空格 -
数组,
key: [v1,v2,v3,v4]
或在行开始使用-
-
map,
key: {k1: v1, k2: v2}
-
常见变量类型示例
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连接,最后使用+代表时区
3.3 注入YAML
-
yaml
的强大之处在于他可以给任意的一个Java类注入属性。 -
示例
-
编写一个实体类
@Data @AllArgsConstructor @NoArgsConstructor @Component @ConfigurationProperties("people") public class People { private String name; private int age; private List<String> car; private String[] wife; private Map<String, String> map; }
-
配置yaml文件
people: name: 张三 age: 18 car: [宝马, 奔驰, 兰博基尼] wife: [蕾姆, 2B] map: {k1: v1, k2: v2}
-
测试
@SpringBootTest class Springboot01HelloSpringBootApplicationTests { @Autowired private People people; @Test void contextLoads() { System.out.println(people); } }
-