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配置文件 启动 ...
随机推荐
- Kali Linux软件更新日报20190622
Kali Linux软件更新日报20190622 (1)laudanum更新到1.0+r36-0kali3,此次更新移除了添加到webshells的链接. (2)mimikatz更新到2.2.0- ...
- linux 中 scp 命令
scp命令用于Linux 之间复制文件和目录.如果想在windows 环境中使用需要安装 linux 命令环境,比如 cmder scp是 secure copy的缩写, scp是linux系统下基于 ...
- 异常检测-基于孤立森林算法Isolation-based Anomaly Detection-3-例子
参考:https://scikit-learn.org/stable/auto_examples/ensemble/plot_isolation_forest.html#sphx-glr-auto-e ...
- 字符分隔符'\1'(\u0001)的困惑
在产生一个随机字符序列时,当要生成的字符串数据为8位时,会不时的在后面加上"\u0001",而多于8位时,例如9位,则不会出现该问题. mark一下!!!!
- 算法习题---5-1代码对齐(UVa1593)
一:题目 将不规范的若干行代码进行对齐.对齐按照最长字符串进行操作.见样例输入 (一)样例输入 ␣␣start:␣␣integer;␣␣␣␣//␣begins␣here stop:␣integer;␣ ...
- Python记录-python执行shell命令
# coding=UTF-8 import os def distcp(): nncheck = os.system('lsof -i:8020') dncheck = os.system('lsof ...
- 一秒解决--------No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
在打war包时候遇到错误: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.0:compile (d ...
- Silence Removal and End Point Detection JAVA Code(音频删除静音与结束判断)
转载自:http://ganeshtiwaridotcomdotnp.blogspot.com/2011/08/silence-removal-and-end-point-detection_29.h ...
- 将WPF转为PDF
https://blog.csdn.net/xgugu1210/article/details/51878104 https://www.cnblogs.com/zeoy/archive/2013/0 ...
- [LeetCode] 855. Exam Room 考场
In an exam room, there are N seats in a single row, numbered 0, 1, 2, ..., N-1. When a student enter ...