spring-boot源码解析

为什么导入dependency时不需要指定版本?
在springboot pom.xml文件中有两个核心依赖,分别是spring-boot-starter-parent和spring-boot-starter-web
在这里插入图片描述
在这里插入图片描述

先看spring-boot-starter-parent中的properties节点
在这里插入图片描述

  1. 工程的Java版本为 1.8 。
  2. 工程代码的编译源文件编码格式为 UTF-8
  3. 工程编译后的文件编码格式为 UTF-8
  4. Maven打包编译的版本

再看Build节点,分别定义了resource和pluginManagement
在这里插入图片描述

我们详细看一下 resources 节点,里面定义了资源过滤,针对 application 的 yml 、 properties 格
式进行了过滤,可以支持支持不同环境的配置,比如 application-dev.yml 、 application-test.yml 、 application-dev.properties 、 application-dev.properties 等等。
pluginManagement 则是引入了相应的插件和对应的版本依赖

最后看spring-boot-dependencies
在这里插入图片描述
这个才是SpringBoot项目的真正管理依赖的项目,里面定义了SpringBoot相关的版本

spring-boot-starter-parent 通过继承 spring-boot-dependencies 从而实现了SpringBoot的版本依
赖管理,所以我们的SpringBoot工程继承spring-boot-starter-parent后已经具备版本锁定等配置了,这也
就是在 Spring Boot 项目中部分依赖不需要写版本号的原因

源码剖析-自动配置

自动配置:根据我们添加的jar包依赖,会自动将一些配置类的bean注册进ioc容器,我们可以需要的地
方使用@autowired或者@resource等注解来使用它。

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

Spring Boot应用的启动入口是@SpringBootApplication注解标注类中的main()方法
@SpringBootApplication : SpringBoot 应用标注在某个类上说明这个类是 SpringBoot 的主配置
类, SpringBoot 就应该运行这个类的 main() 方法启动 SpringBoot 应用。

@SpringBootApplication
在这里插入图片描述
我们主要看后面 3 个注解:@SpringBootConfiguration、@EnableAutoConfiguration、
@ComponentScan三个核心注解,关于这三个核心注解的相关说明具体如下

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

@EnableAutoConfiguration
在这里插入图片描述
Spring 中有很多以 Enable 开头的注解,其作用就是借助 @Import 来收集并注册特定场景相关的
Bean ,并加载到 IOC 容器。

@EnableAutoConfiguration就是借助@Import来收集所有符合自动配置条件的bean定义,并加载到
IoC容器。

我们先来看看@AutoConfigurationPackage注解

@AutoConfigurationPackage
在这里插入图片描述
从上述代码当中也可以看出AutoConfigurationPackage也是一个组合注解。

其中最重要的注解是:
@Import(AutoConfigurationPackages.Registrar.class) ,它是 Spring 框架的底层注解,它的作用就是给容器中导入某个组件类。

它就是将 Registrar 这个组件类导入
到容器中,可查看 Registrar 类中 registerBeanDefinitions 方法
在这里插入图片描述

我们对其中的register方法进行断点调试,发现就是我们启动类的包路径名

在这里插入图片描述
我们再进入register方法
在这里插入图片描述
如果该bean已经注册,则将要注册包名称添加进去
如果该bean尚未注册,则注册该bean,参数中提供的包名称会被设置到bean定义中去

总结:
AutoConfigurationPackages.Registrar这个类就干一个事,注册一个 Bean ,这个 Bean 就是org.springframework.boot.autoconfigure.AutoConfigurationPackages.BasePackages ,它有
一个参数,这个参数是使用了 @AutoConfigurationPackage 这个注解的类所在的包路径,保存自动配置
类以供之后的使用。

@Import(AutoConfigurationImportSelector.class)

@Import({AutoConfigurationImportSelector.class}) :将
AutoConfigurationImportSelector导入到spring容器中,
AutoConfigurationImportSelector 可以帮助 Springboot 应用将所有符合条件的 @Configuration
配置都加载到当前 SpringBoot 创建并使用的 IOC 容器( ApplicationContext )中

在这里插入图片描述
重点是继承了DeferredImportSelector 以及各种aware接口

确定自动配置实现逻辑的入口方法:
跟自动配置逻辑相关的入口方法在 DeferredImportSelectorGrouping 类的 getImports 方法处

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
1.遍历DeferredImportSelectorHolder对象集合deferredImports,deferredImports集合
装了各种ImportSelector,当然这里装的是AutoConfigurationImportSelector

2.利用AutoConfigurationGroup的process方法来处理自动配置的相关逻辑,决定导入哪些配置类(这个是我们分析的重点,自动配置的逻辑全在这了)

在这里插入图片描述
在这里插入图片描述
这里用来处理自动配置类,比如过滤掉不符合匹配条件的自动配置类

【1】,调用getAutoConfigurationEntry方法得到自动配置类放入autoConfigurationEntry对象中
【2】,又将封装了自动配置类的autoConfigurationEntry对象装进autoConfigurationEntries集合
【3】,遍历刚获取的自动配置类

我们先看getAutoConfigurationEntry方法
在这里插入图片描述
【1】得到spring.factories文件配置的所有自动配置类
List configurations = getCandidateConfigurations(annotationMetadata, attributes);
利用LinkedHashSet移除重复的配置类
检查要被排除的配置类,因为有些不是自动配置类,故要抛出异常
configurations = removeDuplicates(configurations);
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
【2】将要排除的配置类移除
configurations.removeAll(exclusions);

【3】因为从spring.factories文件获取的自动配置类太多,如果有些不必要的自动配置类都加载
进内存,会造成内存浪费,因此这里需要进行过滤
注意这里会调用AutoConfigurationImportFilter的match方法来判断是否符合
@ConditionalOnBean,@ConditionalOnClass或@ConditionalOnWebApplication,后面会重点分
析一下
configurations = filter(configurations, autoConfigurationMetadata);

【4】获取了符合条件的自动配置类后,此时触发AutoConfigurationImportEvent事件,
目的是告诉ConditionEvaluationReport条件评估报告器对象来记录符合条件的自动配置类
该事件什么时候会被触发?–> 在刷新容器时调用invokeBeanFactoryPostProcessors后置处
理器时触发
fireAutoConfigurationImportEvents(configurations, exclusions);
【5】将符合条件和要排除的自动配置类封装进AutoConfigurationEntry对象,并返回
return new AutoConfigurationEntry(configurations, exclusions);

然后我们深入一个第一步的getCandidateConfigurations方法
在这里插入图片描述
返回一个类加载器,我们再看看loadFactoryNames方法
在这里插入图片描述
在这里插入图片描述
从代码中我们可以知道,在这个方法中会遍历整个ClassLoader中所有jar包下的spring.factories文件。
spring.factories里面保存着springboot的默认提供的自动配置类。

在这里插入图片描述
我们下面总结AutoConfigurationEntry主要做的事情,
【1】从 spring.factories 配置文件中加载 EnableAutoConfiguration 自动配置类),获取的自动配
置类如图所示。
【2】若 @EnableAutoConfiguration 等注解标有要 exclude 的自动配置类,那么再将这个自动配置类
排除掉;
【3】排除掉要 exclude 的自动配置类后,然后再调用 filter 方法进行进一步的过滤,再次排除一些
不符合条件的自动配置类;
【4】经过重重过滤后,此时再触发 AutoConfigurationImportEvent 事件,告诉
ConditionEvaluationReport 条件评估报告器对象来记录符合条件的自动配置类;
【5】 最后再将符合条件的自动配置类返回。

总结了 AutoConfigurationEntry 方法主要的逻辑后,我们再来细看一下
AutoConfigurationImportSelector 的 filter 方法:
在这里插入图片描述
最后,我们再总结下SpringBoot自动配置的原理,主要做了以下事情:

  1. 从spring.factories配置文件中加载自动配置类;
  2. 加载的自动配置类中排除掉 @EnableAutoConfiguration 注解的 exclude 属性指定的自动配置
    类;
  3. 然后再用 AutoConfigurationImportFilter 接口去过滤自动配置类是否符合其标注注解(若有
    标注的话) @ConditionalOnClass , @ConditionalOnBean 和
    @ConditionalOnWebApplication 的条件,若都符合的话则返回匹配结果;
  4. 然后触发 AutoConfigurationImportEvent 事件,告诉 ConditionEvaluationReport 条件评
    估报告器对象来分别记录符合条件和 exclude 的自动配置类。
  5. 最后spring再将最后筛选后的自动配置类导入IOC容器中

run方法执行流程

在这里插入图片描述
//记录程序运行时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();

// ConfigurableApplicationContext Spring 的上下文
ConfigurableApplicationContext context = null;
Collection exceptionReporters = new ArrayList<>
();
configureHeadlessProperty()

最关键的在下面的六个方法
1.获取并启动监听器
在这里插入图片描述
事件机制在Spring是很重要的一部分内容,通过事件机制我们可以监听Spring容器中正在发生的一些事
件,同样也可以自定义监听事件。Spring的事件为Bean和Bean之间的消息传递提供支持。当一个对象
处理完某种任务后,通知另外的对象进行某些处理,常用的场景有进行某些操作后发送通知,消息、邮
件等情况。

SpringApplicationRunListeners listeners = getRunListeners(args); 看
一下获取的是哪个监听器:
在这里插入图片描述
spring.factory文件
EventPublishingRunListener监听器是Spring容器的启动监听器。
listeners.starting(); 开启了监听事件。

第二步:构造应用上下文环境
在这里插入图片描述
先来看看prepareEnvironment方法
在这里插入图片描述
先来看看prepareEnvironment里的getOrCreateEnvironment方法
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值