SpringBoot 学习笔记
笔记内容:
- 什么是SpringBoot
- 如何编写配置及yaml文件
- SpringBoot自动装配原理(重要)
- SpringBoot集成web开发
- SpringBoot集成Mybatis
- 分布式开发 Dubbo + Zookeeper
- 接口文档 Swagger
- SpringBoot多线程任务调度
- 登录安全验证 SpringSecurity / Shiro
1. 关于SpringBoot
1.1 什么是Spring ?
Spring是一个2003年兴起的轻量级Java开源框架。
Spring是为了解决企业级应用开发的复杂性而创建的,即简化开发。
1.2 Spring是如何简化Java开发的 ?
为了降低Java开发的复杂性,Spring采用了以下 4 种关键策略:
- 基于POJO的轻量级和最小侵入性编程;
- 通过IOC,依赖注入(DI)和面向接口实现松耦合;
- 基于切面(AOP)和惯例进行声明式编程;
- 通过切面和模板减少样式代码;
1.3 什么是SpringBoot ?
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
SpringBoot 基于 Spring 开发,SpringBoot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快捷、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发体验的工具。SpringBoot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 SpringBoot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如Redis、MongoDB、Jpa、RabbitMQ、Quartz等等),SpringBoot 应用这些第三方库几乎可以零配置的开箱即用。
简单来说就是 SpringBoot 其实不是什么新的框架,它默认配置了很多框架的使用方式,就像 maven 整合了所有jar包,而 SpringBoot 整合了所有框架。
2. 关于微服务
2.1 什么是微服务
微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通。要说微服务架构,得先说说过去我们的单体应用架构。
2.2 单体应用架构
所谓单体应用架构(All In One)是指,我们将一个程序的所有功能模块都封装在一个应用中。
无论是ERP、CRM或是其他什么系统,你都会把数据库访问,web访问等等功能放到一个war包里。
- 单体架构优点:易于开发和测试,也十分方便部署;当需要扩展时只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
- 单体架构缺点:哪怕要修改一个非常小的地方,都需要停掉整个服务,重新打包、部署。特别是对于一个大型应用,我们不可能把所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题。
2.3 微服务架构
All In One的架构方式把我们所有的功能单元放在一个应用中,然后把整个应用部署到服务器上。如果负载能力较差,又需要将整个应用进行水平复制,然后扩展,然后再负载均衡。
所谓微服务架构,就是把每个功能模块独立出来,然后进行动态组合,需要的功能才拿来组合,需要多一些时间可以整合多个功能模块。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。
微服务架构优点:
- 节省了资源调用
- 每个功能模块的服务都是一个可替换的、可独立升级的软件
2.4 如何构建微服务
一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被细粒度拆分了,他们作为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新升级一个功能服务单元即可。
但是这种庞大的系统架构给部署和运维带来很大的难度。于是,Spring为我们带来了构建大型分布式微服务的全套、全程产品:
- 构建一个个功能独立的微服务应用单元,可以使用SpringBoot,可以帮我们快速构建一个应用程序;
- 大型分布式网络服务的调用,可以由Spring Cloud完成,实现分布式;
- 在分布式中间,进行流式数据计算、批处理,可以使用Spring Cloud Data Flow。
Spring为我们想清楚了整个应用从开始构建到大型分布式的全流程方案。
3. 第一个SpringBoot程序
Spring官网提供了一个可以快速生成SpringBoot项目的网址: https://start.spring.io/
而IDEA集成了这个网址:(一般会使用IDEA创建SpringBoot项目)
通过以上方式即可创建一个SpringBoot项目。
pom.xml中基本的依赖:
<dependencies>
<!-- 所有的springboot依赖都是以"spring-boot-starter-"开头 -->
<!-- 启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- web依赖:tomcat、dispatcherServlet、xml -->
<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>
<!--devtools热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打jar包的插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
另外SpringBoot有一个小彩蛋:在Resource目录下新建banner.txt文件,可通过其修改日志中的banner图样式。
4. SpringBoot自动装配原理
pom.xml:
- 核心依赖在父工程中:helloworld -> spring-boot-starter-parent -> spring-boot-dependencies
- 我们在引入SpringBoot依赖时无需指定版本,就是因为有这些版本仓库
启动器:
-
<!-- 启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
- 启动器:就是SpringBoot的启动场景。比如spring-boot-starter-web,它就会帮我们自动导入web环境所有的依赖
- SpringBoot会将所有功能场景,都变为一个个的启动器
spring-boot-starter-xxx
。我们要使用什么功能,就只需要找到对应的启动器就可以了
主程序:
@SpringBootApplication // 标注这个类是SpringBoot的启动类
public class HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}
注解
@SpringBootConfiguration:SpringBoot的配置
@Configuration:Spring配置类
@Component:说明@SpringBootConfiguration也是一个Spring的组件
@EnableAutoConfiguration:自动配置
@AutoConfigurationPackage:自动配置包
@Import({Registrar.class}):自动配置`包注册`
@Import({AutoConfigurationImportSelector.class}):自动配置导入选择
// 获取所有的配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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:自动配置的核心文件
Properties properties = PropertiesLoaderUtils.loadProperties(resource); 所有资源加载到配置类中
结论:SpringBoot所有自动配置都是在启动的时候启动并加载:spring.factories所有的配置类都在这里面,但不一定生效,要判断条件是否成立,只要导入了对应的start就有对应的启动器了,有了启动器自动装配就会生效,然后就配置成功!
-
SpringBoot启动时从类路径下的/META-INF/spring.factories中获取EnableAutoConfiguration指定的值;
-
将这些值作为自动配置类导入容器,自动配置类就生效,帮我们进行自动配置;
-
以前需要自己配置的东西,自动配置类都帮我们解决了。
-
整个JavaEE解决方案和自动配置都在包spring-boot-autoconfigure的jar包中;
-
它将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中;
-
它会给容器中导入非常多的配置类(xxxAutoConfiguration)。就是给容器中导入这个场景所需要的所有组件(component),并配置(configure)好这些组件;
-
有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;
SpringApplication
不简单的方法
我最初以为就是运行了一个main方法,没想到却开启了一个服务;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
SpringApplication.run分析
分析该方法主要分两部分,一部分是SpringApplication的实例化,二是run方法的执行;
SpringApplication
这个类主要做了以下四件事情:
-
推断应用的类型是普通的项目还是Web项目
-
查找并加载所有可用初始化器 , 设置到initializers属性中
-
找出所有的应用程序监听器,设置到listeners属性中
-
推断并设置main方法的定义类,找到运行的主类
查看构造器:
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
// ......
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances();
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
Run方法流程分析
视频参考:【狂神说Java】SpringBoot最新教程IDEA版通俗易懂