Springboot(1)
一.介绍
1.什么是Springboot
- 随着 Spring不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。SpringBoot 正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用 Spring 、更容易的集成各种常用的中间件、开源软件;
- Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。**Spring Boot以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring配置。**同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),SpringBoot 应用中这些第三方库几乎可以零配置的开箱即用。
- 简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,springboot整合了所有的框架 。
2.SpringBoot优点
- 创建独立Spring应用
- 内嵌web服务器
- 自动starter依赖,简化构建配置
- 自动配置Spring以及第三方功能
- 提供生产级别的监控、健康检查及外部化配置
- 无代码生成、无需编写XML
3.微服务架构
- 微服务是一种架构风格
- 一个应用拆分为一组小型服务
- 每个服务运行在自己的进程内,也就是可独立部署和升级
- 服务之间使用轻量级HTTP交互
- 服务围绕业务功能拆分
- 可以由全自动部署机制独立部署
- 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术
二.入门
1.项目创建方式一:使用Spring Initializr 的 Web页面创建项目
- 打开 https://start.spring.io/
- 填写项目信息
- 点击”Generate Project“按钮生成项目;下载此项目
- 解压项目包,并用IDEA以Maven项目导入,一路下一步即可,直到项目导入完毕。
- 如果是第一次使用,可能速度会比较慢,包比较多、需要耐心等待一切就绪。
2.项目创建方式二:使用 IDEA 直接创建项目(推荐)
项目结构分析:
通过上面步骤完成了基础项目的创建。就会自动生成以下文件:
1、程序的主启动类
2、一个 application.properties 配置文件
3、一个 测试类
4、一个 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.11</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.liqingfeng</groupId>
<artifactId>springboot-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-01</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- web场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
现在我们写一个controller业务
1、在主启动类的同级目录下新建一个controller包(必须是同级目录下,底层写好的),并新建一个HelloController类
2、从主程序类中启动项目(执行main方法),请求hello请求,页面显示返回的数据,OK
将项目打成jar包,发布出去
1.打包之前,在pom.xml中配置打包时跳过test测试(节省打包时间,且jar包也不会太大)
<!--在工作中,很多情况下我们打包是不想执行测试用例的(测试影响数据库数据),所以跳过测试-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--跳过项目运行测试用例-->
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
2.执行打包操作
3.打包成功会在target目录下看到对应jar包
4.将该jar包拖到桌面并执行cmd的java -jar命令执行jar包
5.浏览器请求url,访问OK
3.自定义banner启动图标
在resources目录下新建一个banner.txt,其内容可在https://www.bootschool.net/ascii
生成
三.自动配置原理(重点)
我们之前写的springboot01 web项目,执行主启动类main方法就能运行服务。到底是怎么运行的呢?
1.从pom.xml文件探究起
点进去spring-boot-starter-parent
,发现还有一个父依赖spring-boot-dependencies
这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心;
以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了
我们pom.xml要开发web应用,如下配置了,就不用写版本号,因为依赖中版本已控制好,而且spring-boot-starter-web叫web场景启动器,该启动器会导入web开发中正常运行所依赖的jar包(其中包含嵌入的tomcat服务器)
2.启动器
以后我们看到的springboot-boot-starter-xxx
,就是spring-boot的各场景启动器
看到:xxx-spring-boot-starter
就是第三方为我们提供的,简化开发的场景启动器
官网启动器详解:https://docs.spring.io/spring-boot/docs/2.4.11/reference/html/using-spring-boot.html#using-boot-starter
SpringBoot将所有的功能场景都抽取出来,做成一个个的starter (启动器),只需要在项目中引入这些starter即可,所有相关的依赖都会导入进来 , 我们要用什么功能就导入什么样的场景启动器即可,我们未来也可以自己自定义 starter
3.主启动类
@SpringBootApplication
public class Springboot01Application {
public static void main(String[] args) {
SpringApplication.run(Springboot01Application.class, args);
}
}
@SpringBootApplication注解
作用:标注在某个类上说明这个类是SpringBoot的主配置类 , SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;
进入这个注解:可以看到上面还有很多其他注解!
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("......")
1.@ComponentScan
作用:自动扫描并加载符合条件的bean组件到IOC容器中,spring中有讲解
2.@SpringBootConfiguration
我们继续进去这个@SpringBootConfiguration注解查看,该注解又是一个@Configuration
点@Configuration注解查看,@Configuration注解又是一个 @Component
3.@Configuration
功能:作用的类是一个配置类(配置类就是对应Spring的xml 配置文件)
- Full模式(@Configuration(proxyBeanMethods = true)),是默认模式
- Lite模式(@Configuration(proxyBeanMethods = false))
两种模式推荐最佳实战
- 配置类的bean组件之间有依赖关系用Full模式(每个@Bean方法被调用多少次返回的bean组件都是单实例的(配置类里面使用@Bean标注在方法上给容器注册组件默认是单实例的),也就是这些bean组件地址是同一个,因为会去spring容器中找这个bean组件)
- 配置类的bean组件之间无依赖关系用Lite模式(每个@Bean方法被调用多少次返回的bean组件都是新创建的,也就是这些bean组件地址不是同一个,因为会直接new一个bean组件返回,不会去spring容器中找。不过,可以加速容器启动过程、减少判断)
4.@Component
功能:作用的类,该类是spring容器里的bean组件。
所以说,主启动类本身也是Spring中的一个配置类也是一个bean组件,负责启动应用!
5.@EnableAutoConfiguration(重要的注解)
功能:开启自动配置功能
6.@AutoConfigurationPackage
@import : 给spring容器中导入Registrar bean组件
Registrar类作用:将主启动类的所在包及包下面所有子包里面的所有bean组件注册到Spring容器
下图通过debug追踪AutoConfigurationPackage.class.getName()就是扫描主启动类(Springboot01Application)包下的所有组件
7.@Import
- @Import( ):给spring容器导入指定的bean组件
- @Import(AutoConfigurationImportSelector.class):给spring容器注册AutoConfigurationImportSelector bean组件,而AutoConfigurationImportSelector是自动配置导入选择器,它被spring容器托管,那么它会导入哪些自动配置类呢?
1、AutoConfigurationImportSelector类中有一个这样的方法
// 获得候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//这里的getSpringFactoriesLoaderFactoryClass()方法
//返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration
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;
}
2、这个方法又调用了 SpringFactoriesLoader 类的静态方法!我们进入SpringFactoriesLoader类loadFactoryNames() 方法
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
//这里它又调用了 loadSpringFactories 方法
return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
3、我们继续点击查看 loadSpringFactories 方法
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
//获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身
Map<String, String> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
//去获取一个资源 "META-INF/spring.factories"
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
//将读取到的资源遍历,封装成为一个Properties
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.