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配置文件 启动 ...
随机推荐
- JEECG Hibernate 自动更新 持久化
Hibernate不调用update却自动更新 - 七郎 - 博客园http://www.cnblogs.com/yangy608/p/4073941.html hibernate自动更新持久化类的问 ...
- (转)Darknet模型与Tensorflow模型相互转换
目前darknet框架下的模型训练都是在C环境下训练的,难免较为晦涩,如果能将模型转换到Tensorflow环境下完成模型的训练,在将训练好的权重转为Darknet可以识别的权重部署到实际应用中.这样 ...
- shell编程系列19--文本处理三剑客之awk中的字符串函数
shell编程系列19--文本处理三剑客之awk中的字符串函数 字符串函数对照表(上) 函数名 解释 函数返回值 length(str) 计算字符串长度 整数长度值 index(str1,str2) ...
- C++11使用make_shared的优势和劣势
Why Make_shared ? C++11 中引入了智能指针, 同时还有一个模板函数 std::make_shared 可以返回一个指定类型的 std::shared_ptr, 那与 std::s ...
- xcopy命令拷贝文件夹和文件
文件夹: xcopy /r /y 'c:123\' 'D:\123\' 文件: echo f | xcopy /d /r /k c:\index2.htm c:\index.htm
- 我非要捅穿这 Neutron(二)上层资源模型篇
目录 文章目录 目录 Neutron 的资源模型 Network 运营商网络和租户网络 创建运营商网络 创建租户网络 创建外部网络 Network 小结 Subnet IP 核心网络服务 Subnet ...
- Spring cloud微服务安全实战-3-1 API安全 常见的安全机制
不考虑微服务这种复杂的环境下,只是写一个简单的api的时候,如何来保证api的安全. 什么是API
- Java Utils工具类大全
源码和jar见:https://github.com/evil0ps/utils #Java Utils --- 封装了一些常用Java操作方法,便于重复开发利用. 另外希望身为Java牛牛的你们一起 ...
- 转 mysql mysql命令行中执行sql的几种方式总结
https://www.jb51.net/article/96394.htm 1.直接输入sql执行 MySQL> select now(); +---------------------+ | ...
- Jmeter性能测试实战教程系列-搭建分布式性能测试环境(五)
Jmeter 是java 应用,对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至会引起JAVA内存溢出错误.为了让jmeter工具 ...