springboot笔记03——quickstart程序原理
一、前言
一个quickstart程序仅仅让我们初步了解一个框架,我们还需要透过现象看本质才能学好一个框架。所以这篇文章分析一下我上次写的springboot的入门程序。
二、原理分析
1、依赖分析
1.1、父模块的parent结点
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
</parent>
1.2、点进去spring-boot-starter-parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
1.3、点进去spring-boot-dependencies
<properties>
<activemq.version>5.15.9</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
...
<commons-pool.version>1.6</commons-pool.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
...
</dependencies>
</dependencyManagement>
在spring-boot-dependencies中对大部分的jar包进行版本管理,再点进去每一个所引用到的starter里面就能看见每个jar包具体的版本。在spring-boot-dependencies已经定义了版本号的jar包,在其他地方引用就不需再写版本号了,而在spring-boot-dependencies没有被依赖的jar包,自行引入的时候就需要写版本号。 特别之处就是spring-boot-dependencies中使用了< dependencyManagement >,dependencyManagement 用于版本管理,声明jar,并不实际引入jar,子模块默认不继承,子模块需要的jar需要在子模块引入,并不需重新写版本号,若子模块定义了新的版本号,则优先使用子模块中的版本。而使用 < dependencies >就是直接引入jar。
(我的入门程序只引用到了spring-boot-starter-web和spring-boot-starter-test)
1.4、Tomcat在哪里
以往的spring程序都需要把项目发布在Tomcat中,然后手动启动Tomcat服务器进行测试。Springboot的入门程序只需要Run启动类就可以访问url了。这是为什么呢?
我们先点进去spring-boot-starter-web(这里没有写版本号)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
再点进去spring-boot-starter-tomcat
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.21</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>tomcat-annotations-api</artifactId>
<groupId>org.apache.tomcat</groupId>
</exclusion>
</exclusions>
</dependency>
...
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>9.0.21</version>
<scope>compile</scope>
</dependency>
**Springboot内嵌了一个Tomcat ! **Springboot2.1.6内嵌的Tomcat版本号为9.0.21。
2、注解分析
2.1、主启动类中的 @SpringBootApplication
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
}
三个重点注解:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan。下面来分析一下这三个注解。
2.1.1、@SpringBootConfiguration
Springboot配置类。标注在某个类上,表示这是一个Springboot的配置类。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
用了Spring的@Configuration,表明这是一个配置类,相当于配置文件。
2.1.2、@EnableAutoConfiguration
自动配置
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
}
两个关键注解:@AutoConfigurationPackage、@Import。
2.1.2.1 、@AutoConfigurationPackage
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
@Import({Registrar.class}) 引入了Registrar组件。一个很关键的步骤:将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器。 就是由这一句注解完成的。
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
}
}
2.1.2.2 、@Import({AutoConfigurationImportSelector.class})
将一些快速地导入到Spring容器中
我们可以看getCandidateConfigurations方法中引用的SpringFactoriesLoader.loadFactoryNames方法。
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
Springboot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration 指定的值,根据这些值将自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。
2.1.3、@ComponentScan
相当于Spring配置文件中的,作用就是将不需要扫描的组件在这里声明。
<context:component-scan base-package="xxx">
<context:exclude-filter type="annotation" expression="xxxx"/>
</context:component-scan>
总结
知所以然才能知其所以。学习原理非常重要。
springboot笔记03——quickstart程序原理的更多相关文章
- 机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理、源码解析及测试
机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理.源码解析及测试 关键字:决策树.python.源码解析.测试作者:米仓山下时间:2018-10-2 ...
- springboot笔记02——快速入门quickstart
前言 学习一个新的框架,往往会用一个quickstart快速入门,这次就写一下springboot的quickstart程序. 开发环境 JDK 1.8 Springboot 2.1.6 Maven ...
- SaToken学习笔记-03
SaToken学习笔记-03 如果排版有问题,请点击:传送门 核心思想 所谓权限验证,验证的核心就是一个账号是否拥有一个权限码 有,就让你通过.没有?那么禁止访问! 再往底了说,就是每个账号都会拥有一 ...
- Java:并发笔记-03
Java:并发笔记-03 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 3. 共享模型之管程-2 本章内容-2 Monitor wait/notify 3.6 ...
- 《30天自制操作系统》笔记(03)——使用Vmware
<30天自制操作系统>笔记(03)——使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测 ...
- Java IO学习笔记:概念与原理
Java IO学习笔记:概念与原理 一.概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络)读入到内存 中,形成了 ...
- JS自学笔记03
JS自学笔记03 1.函数练习: 如果函数所需参数为数组,在声明和定义时按照普通变量名书写参数列表,在编写函数体内容时体现其为一个数组即可,再传参时可以直接将具体的数组传进去 即 var max=ge ...
- C++ GUI Qt4学习笔记03
C++ GUI Qt4学习笔记03 qtc++spreadsheet文档工具resources 本章介绍创建Spreadsheet应用程序的主窗口 1.子类化QMainWindow 通过子类化QM ...
- Redis:学习笔记-03
Redis:学习笔记-03 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 7. Redis配置文件 启动 ...
随机推荐
- Java基础 do-while 简单示例
JDK :OpenJDK-11 OS :CentOS 7.6.1810 IDE :Eclipse 2019‑03 typesetting :Markdown code ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#region(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#region(C# 参考) 1.返回顶部 1. #region(C# 参考) 2015/07/20 利用 #region,可以 ...
- flutter PopupMenuButton弹出式菜单列表
import 'package:flutter/material.dart'; class PopupMenuButtonDemo extends StatefulWidget { @override ...
- typescript接口扩展
/* typeScript中的接口 接口扩展 */ /* 接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用.接口定义了某一批 ...
- 我非要捅穿这 Neutron(二)上层资源模型篇
目录 文章目录 目录 Neutron 的资源模型 Network 运营商网络和租户网络 创建运营商网络 创建租户网络 创建外部网络 Network 小结 Subnet IP 核心网络服务 Subnet ...
- 泡泡一分钟:Topomap: Topological Mapping and Navigation Based on Visual SLAM Maps
Topomap: Topological Mapping and Navigation Based on Visual SLAM Maps Fabian Bl¨ochliger, Marius Feh ...
- 使用SoapUI测试wsdl
webservice服务wsdl地址:http://localhost:8080/services/HelloWorld?wsdl new project: new soap project: 调用测 ...
- clientHeight,offsetHeight,scrollHeight迷一样的三个值
https://blog.csdn.net/qq_39083004/article/details/78498178 https://www.imooc.com/article/17571 推荐 o ...
- pipline中替换tag变量
实验架构: 192.168.0.96 gitlab 192.168.0.97 jenkins 192.168.0.98 harbor.docker集群 说明:下面代码编译镜像那一步的代码必须靠左,目的 ...
- 【Leetcode_easy】832. Flipping an Image
problem 832. Flipping an Image solution1: class Solution { public: vector<vector<int>> f ...