持续原创输出,点击上方蓝字关注我

目录

  • 前言
  • 源码版本
  • @SpringBootApplication干了什么?
  • @EnableAutoConfiguration干了什么?
  • 总结

前言

为什么Spring Boot这么火?因为便捷,开箱即用,但是你思考过为什么会这么便捷吗?传统的SSM架构配置文件至少要写半天,而使用Spring Boot之后只需要引入一个starter之后就能直接使用,why???

原因很简单,每个starter内部做了工作,比如Mybatis的启动器默认内置了可用的SqlSessionFactory

至于如何内置的?Spring Boot 又是如何使其生效的?这篇文章就从源码角度介绍一下Spring Boot的自动配置原理。

源码版本

作者Spring Boot是基于2.4.0。每个版本有些变化,读者尽量和我保持一致,以防源码有些出入。

@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 {}

上方标注了三个重要的注解,如下:

  1. @SpringBootConfiguration:其实就是@Configuration,因此主启动类可以当做配置类使用,比如注入Bean等。
  2. @EnableAutoConfiguration:这个注解牛批了,名字就不一样,开启自动配置,哦,关键都在这了.....
  3. @ComponentScan:包扫描注解。

经过以上的分析,最终定位了一个注解@EnableAutoConfiguration,顾名思义,肯定和自动配置有关,要重点分析下。

@EnableAutoConfiguration干了什么?

想要知道做了什么肯定需要看源码,如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

上方标注了两个重要的注解,如下:

  1. @AutoConfigurationPackage:自动配置包注解,默认将主配置类(@SpringBootApplication)所在的包及其子包里面的所有组件扫描到IOC容器中。
  2. @Import:该注解不必多说了,前面文章说过很多次了,这里是导入了AutoConfigurationImportSelector,用来注入自动配置类。

以上只是简单的分析了两个注解,下面将会从源码详细的介绍一下。

@AutoConfigurationPackage

这个注解干了什么?这个需要看下源码,如下;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}

重要的还是@Import注解,导入了AutoConfigurationPackages.Registrar,这个类是干什么的?源码如下图:

其实就两个方法,但是的最重要的就是registerBeanDefinitions方法,但是这个方法不用看,肯定是注入Bean,这里的重点是注入哪些Bean,重点源码如下:

//获取扫描的包
new PackageImports(metadata).getPackageNames().toArray(new String[0])

跟进代码,主要逻辑都在#PackageImports.PackageImports()这个构造方法中,源码解析如下图:

从上面源码分析可以知道,这里扫描的包名是由两部分组成,分别如下:

  1. @AutoConfigurationPackage注解中的两个属性解析得来的包名。
  2. 注解AutoConfigurationPackage所在的包名,即是@SpringBootApplication所在的包名。

@AutoConfigurationPackage默认将主配置类(@SpringBootApplication)所在的包及其子包里面的所有组件扫描到IOC容器中。

@Import(AutoConfigurationImportSelector.class)

这个注解不用多说了,最重要的就是AutoConfigurationImportSelector,我们来看看它的继承关系,如下图:

这个类的继承关系还是挺简单的,实现了Spring中的xxAware注入一些必要的组件,但是最值得关心的是实现了一个DeferredImportSelector这个接口,这个接口扩展了ImportSelector,也改变了其运行的方式,这个在后面章节会介绍。

「注意」:这个类会导致一个误区,平时看到xxxSelector已经有了反射弧了,肯定会在selectImports()方法上DEBUG,但是这个类压根就没执行该方法,我第一次看也有点怀疑人生了,原来它走的是DeferredImportSelector的接口方法。

其实该类真正实现逻辑的方法是process()方法,但是主要加载自动配置类的任务交给了getAutoConfigurationEntry()方法,具体的逻辑如下图:

上图的逻辑很简单,先从spring.factories文件中获取自动配置类,在去掉@SpringBootApplication中定义排除的自动配置类。

上图中的第步就是从META-INF/spring.factories中加载自动配置类,代码很简单,在上一篇分析启动流程的时候也有很多组件是从spring.facotries文件中加载的,代码都类似。

springboot-autoconfigure中的spring.facotries文件内置了很多自动配置类,如下:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
................

了解了Spring Boot 如何加载自动配置类,那么自定义一个自动配置类也是很简单了,后续章节教你如何定制自己的自动配置类,里面还是有很多门道的.....

总结

本文从源码角度分析了Spring Boot的自动配置是如何加载的,其实分析起来很简单,希望作者的这篇文章能帮助你更深层次的了解Spring Boot

另外作者的第一本PDF书籍已经整理好了,由浅入深的详细介绍了Mybatis基础以及底层源码,有需要的朋友公号回复关键词「Mybatis进阶」即可获取,目录如下:

头秃了,Spring Boot 自动配置了解一波~的更多相关文章

  1. Spring Boot自动配置原理与实践(一)

    前言 Spring Boot众所周知是为了简化Spring的配置,省去XML的复杂化配置(虽然Spring官方推荐也使用Java配置)采用Java+Annotation方式配置.如下几个问题是我刚开始 ...

  2. Springboot 系列(三)Spring Boot 自动配置原理

    注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring ...

  3. Spring Boot自动配置与Spring 条件化配置

    SpringBoot自动配置 SpringBoot的自动配置是一个运行时(应用程序启动时)的过程,简化开发时间,无需浪费时间讨论具体的Spring配置,只需考虑如何利用SpringBoot的自动配置即 ...

  4. Spring Boot自动配置原理、实战

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  5. Spring Boot自动配置

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  6. Spring boot 自动配置自定义配置文件

    示例如下: 1.   新建 Maven 项目 properties 2.   pom.xml <project xmlns="http://maven.apache.org/POM/4 ...

  7. Spring Boot自动配置原理(转)

    第3章 Spring Boot自动配置原理 3.1 SpringBoot的核心组件模块 首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量: 我们cd到spring-boot- ...

  8. Spring Boot自动配置如何工作

    通过使用Mongo和MySQL DB实现的示例,深入了解Spring Boot的@Conditional注释世界. 在我以前的文章“为什么选择Spring Boot?”中,我们讨论了如何创建Sprin ...

  9. Spring boot --- 自动配置

    spring boot 自动配置 指的是针对很多spring 应用程序常见的应用功能,spring boot 能自动提供相关配置. spring boot 自动配置加载     Spring boot ...

随机推荐

  1. kali 運行 chrome

    0x00前提 已經安裝好google chrome . 0x01 在終端執行命令: google-chrome,發現如圖: 錯誤提示:在root下只能使用 --no-sandbox選項來運行chrom ...

  2. Django创建表时报错django.db.utils.InternalError: (1366问题解决记录

    问题出现 执行Python manage.py makemigrations生成创建表的py文件 执行python manage.py migrate创建数据表 界面出现报错 问题原因 网上搜索原因, ...

  3. 实战:xfs文件系统的备份和恢复

    概述 XFS提供了 xfsdump 和 xfsrestore 工具协助备份XFS文件系统中的数据.xfsdump 按inode顺序备份一个XFS文件系统. centos7选择xfs格式作为默认文件系统 ...

  4. Asp.Net实现局部刷新,ScriptManager和UpdatePanel控件的使用

    <asp:CheckBoxList ID="LimitCollegeNo" runat="server" CellPadding="5" ...

  5. poj1011 Sticks (搜索经典好题)

    poj1011 Sticks 题目连接: poj1011 Description George took sticks of the same length and cut them randomly ...

  6. update不能直接使用select的返回结果

    update不能直接使用select的返回结果,这是会报错的,这是SQL的语法规定的,若想在update中与select结合使用,sql需要这样写: 1.其中field1,field2为表中的字段名 ...

  7. webmagic源码浅析

    webmagic简介 webmagic可以说是中国传播度最广的Java爬虫框架,https://github.com/code4craft/webmagic,阅读相关源码,获益良多.阅读作者博客[代码 ...

  8. JS里各种类型的循环

    for... for( 初始条件; 判断条件; 递增条件 ) { ... } for ... in 可以把一个对象里面的所有属性依次循环出来 var person = { name: 'Jack', ...

  9. 用node.js给C#写一个数据表的实体类生成工具

    虽然微软提供了T4模板,但是我感觉非常难用.哪儿比得上直接用脚本来写模板来的爽. 因为要给一个老项目做周边的工具,需要连接到数据库. 我习惯性用EntityFrameworkCore来做,因为毕竟从出 ...

  10. 理解 Android Binder 机制(一):驱动篇

    Binder的实现是比较复杂的,想要完全弄明白是怎么一回事,并不是一件容易的事情. 这里面牵涉到好几个层次,每一层都有一些模块和机制需要理解.这部分内容预计会分为三篇文章来讲解.本文是第一篇,首先会对 ...