SpringBoot原理深入及源码剖析

目录

1、SpringBoot原理深入及源码剖析

2、依赖管理

问题:(1)为什么导入dependency时不需要指定版本?

2.1.spring-boot-starter-parent依赖

2)问题2: spring-boot-starter-parent父依赖启动器的主要作用是进行版本统一管理,那么项目运行依赖的JAR包是从何而来的?

2. spring-boot-starter-web依赖

3.自动配置

问题:Spring Boot到底是如何进行自动配置的,都把哪些组件进行了自动配置?

3.1 @SpringBootConfiguration注解

3.2 @EnableAutoConfiguration注解

 3.3@ComponentScan注解

1、SpringBoot原理深入及源码剖析

传统的Spring框架实现一个Web服务,需要导入各种依赖JAR包,然后编写对应的XML配置文件
等,相较而言,Spring Boot显得更加方便、快捷和高效。那么,Spring Boot究竟如何做到这些的呢?
接下来分别针对Spring Boot框架的依赖管理、自动配置通过源码进行深入分析

2、依赖管理

问题:(1)为什么导入dependency时不需要指定版本?

在Spring Boot入门程序中,项目pom.xml文件有两个核心依赖,分别是spring-boot-starter-parent和spring-boot-starter-web,关于这两个依赖的相关介绍具体如下:

2.1.spring-boot-starter-parent依赖

<!-- Spring Boot父项目依赖管理 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent<11./artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

上述代码中,将spring-boot-starter-parent依赖作为Spring Boot项目的统一父项目依赖管理,并将项目版本号统一为2.2.2.RELEASE,该版本号根据实际开发需求是可以修改的
使用“Ctrl+鼠标左键”进入并查看spring-boot-starter-parent底层源文件,发现spring-bootstarter-parent的底层有一个父依赖spring-boot-dependencies,核心代码具体如下

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>

继续查看spring-boot-dependencies底层源文件:

从spring-boot-dependencies底层源文件可以看出,该文件通过标签对一些常用技术框架的依赖文件进行了统一版本号管理,例如activemq、spring、tomcat等,都有与Spring Boot 2.2.2版本相匹配的版本,这也是pom.xml引入依赖文件不需要标注依赖文件版本号的原因。
需要说明的是,如果pom.xml引入的依赖文件不是 spring-boot-starter-parent管理的,那么在
pom.xml引入依赖文件时,需要使用标签指定依赖文件的版本号。

2)问题2: spring-boot-starter-parent父依赖启动器的主要作用是进行版本统一管理,那么项目运行依赖的JAR包是从何而来的?

2. spring-boot-starter-web依赖

spring-boot-starter-web依赖文件源码

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>从上述代码可以发现,spring-boot-starter-web依赖启动器的主要作用是提供Web开发场景所需的底层
所有依赖
正是如此,在pom.xml中引入spring-boot-starter-web依赖启动器时,就可以实现Web场景开发,而不
需要额外导入Tomcat服务器以及其他Web依赖文件等。当然,这些引入的依赖文件的版本号还是由
spring-boot-starter-parent父依赖进行的统一管理。
有哪些starter:
https://github.com/spring-projects/spring-boot/tree/v2.1.0.RELEASE/spring-boot-project/spring-bo
ot-starters
https://mvnrepository.com/search?q=starter
Spring Boot除了提供有上述介绍的Web依赖启动器外,还提供了其他许多开发场景的相关依赖,
我们可以打开Spring Boot官方文档,搜索“Starters”关键字查询场景依赖启动器
<artifactId>spring-boot-starter-json</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>tomcat-embed-el</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>

从上述代码可以发现,spring-boot-starter-web依赖启动器的主要作用是提供Web开发场景所需的底层所有依赖正是如此,在pom.xml中引入spring-boot-starter-web依赖启动器时,就可以实现Web场景开发,而不需要额外导入Tomcat服务器以及其他Web依赖文件等。当然,这些引入的依赖文件的版本号还是由spring-boot-starter-parent父依赖进行的统一管理。 

3.自动配置

问题:Spring Boot到底是如何进行自动配置的,都把哪些组件进行了自动配置?

 @SpringBootApplication内部源码进行分析,观察其做了哪些工作:

@Target({ElementType.TYPE}) //注解的适用范围,Type表示注解可以描述在类、接口、注解或枚举中
@Retention(RetentionPolicy.RUNTIME) //表示注解的生命周期,Runtime运行时
@Documented //表示注解可以记录在javadoc中
@Inherited //表示可以被子类继承该注解
@SpringBootConfiguration // 标明该类为配置类

@EnableAutoConfiguration // 启动自动配置功能
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes =
TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes =
AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    // 根据class来排除特定的类,使其不能加入spring容器,传入参数value类型是class类型。
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class<?>[] exclude() default {};
    // 根据classname 来排除特定的类,使其不能加入spring容器,传入参数value类型是class的全
类名字符串数组。
    @AliasFor(annotation = EnableAutoConfiguration.class)
    String[] excludeName() default {};
    // 指定扫描包,参数是包名的字符串数组。
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
    // 扫描特定的包,参数类似是Class类型数组。
    @AliasFor(annotation = ComponentScan.class, attribute =
    "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

从上述源码可以看出,@SpringBootApplication注解是一个组合注解,前面 4 个是注解的元数据
信息, 我们主要看后面 3 个注解:@SpringBootConfiguration、@EnableAutoConfiguration、
@ComponentScan三个核心注解
,关于这三个核心注解的相关说明具体如下:

3.1 @SpringBootConfiguration注解

@SpringBootConfiguration : SpringBoot 的配置类,标注在某个类上,表示这是一个 SpringBoot
的配置类。
查看@SpringBootConfiguration注解源码,核心代码具体如下。 

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration // 配置类的作用等同于配置文件,配置类也是容器中的一个对象
public @interface SpringBootConfiguration {
}

从上述源码可以看出,@SpringBootConfiguration注解内部有一个核心注解@Configuration,该
注解是Spring框架提供的,表示当前类为一个配置类(XML配置文件的注解表现形式),并可以被组件扫描器扫描。由此可见,@SpringBootConfiguration注解的作用与@Configuration注解相同,都是标识一个可以被组件扫描器扫描的配置类,只不过@SpringBootConfiguration是被Spring Boot进行了重新封装命名而已

3.2 @EnableAutoConfiguration注解

 @EnableAutoConfiguration :开启自动配置功能,以前由我们需要配置的东西,现在由 SpringBoot帮我们自动配置,这个注解就是 Springboot 能实现自动配置的关键。
同样,查看该注解内部查看源码信息,核心代码具体如下

// 自动配置包
@AutoConfigurationPackage

// Spring的底层注解@Import,给容器中导入一个组件;
// 导入的组件是AutoConfigurationPackages.Registrar.class
@Import(AutoConfigurationImportSelector.class)

// 告诉SpringBoot开启自动配置功能,这样自动配置才能生效。
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    // 返回不会被导入到 Spring 容器中的类
    Class<?>[] exclude() default {};

    // 返回不会被导入到 Spring 容器中的类名
    String[] excludeName() default {};
}

可以发现它是一个组合注解, Spring 中有很多以 Enable 开头的注解,其作用就是借助 @Import
来收集并注册特定场景相关的 Bean ,并加载到 IOC 容器。@EnableAutoConfiguration就是借助@Import来收集所有符合自动配置条件的bean定义,并加载到IoC容器。

总结
因此springboot底层实现自动配置的步骤是:
1. springboot应用启动;
2. @SpringBootApplication起作用;
3. @EnableAutoConfiguration;
4. @AutoConfigurationPackage:这个组合注解主要是
@Import(AutoConfigurationPackages.Registrar.class),它通过将Registrar类导入到容器中,而
Registrar类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到springboot创建管理的
容器中;
5. @Import(AutoConfigurationImportSelector.class):它通过将AutoConfigurationImportSelector
类导入到容器中,AutoConfigurationImportSelector类作用是通过selectImports方法执行的过程
中,会使用内部工具类SpringFactoriesLoader,查找classpath上所有jar包中的METAINF/spring.factories进行加载,实现将配置类信息交给SpringFactory加载器进行一系列的容器创建过程

 3.3@ComponentScan注解

 @ComponentScan注解具体扫描的包的根路径由Spring Boot项目主程序启动类所在包位置决定
在扫描过程中由前面介绍的@AutoConfigurationPackage注解进行解析,从而得到Spring Boot项目主、程序启动类所在包的具体位置


 


 

 


 


 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值