前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >玩转 Spring Boot 原理篇(自动装配源码剖析)

玩转 Spring Boot 原理篇(自动装配源码剖析)

作者头像
一猿小讲
发布2022-04-12 14:42:47
5690
发布2022-04-12 14:42:47
举报
文章被收录于专栏:一猿小讲一猿小讲

0.

0.0. 历史文章整理

玩转 Spring Boot 入门篇

玩转 Spring Boot 集成篇(MySQL、Druid、HikariCP)

玩转 Spring Boot 集成篇(MyBatis、JPA、事务支持)

玩转 Spring Boot 集成篇(Redis)

玩转 Spring Boot 集成篇(Actuator、Spring Boot Admin)

玩转 Spring Boot 集成篇(RabbitMQ)

玩转 Spring Boot 集成篇(@Scheduled、静态、动态定时任务)

玩转 Spring Boot 集成篇(任务动态管理代码篇)

玩转 Spring Boot 集成篇(定时任务框架Quartz)

玩转 Spring Boot 原理篇(源码环境搭建)

玩转 Spring Boot 原理篇(核心注解知多少)

玩转 Spring Boot 原理篇(自动装配前凑之自定义Starter)

0.1. Spring Boot 自动装配原理

  • Spring Boot 通过 @EnableAutoConfiguration 注解开启自动配置,@EnableAutoConfiguration 注解可以帮助 SpringBoot 应用将所有符合条件的 @Configuration 配置都加载到 IOC 容器,就跟“八爪鱼”一样。
  • 借助 Spring 框架工具类 SpringFactoriesLoader 的支持,可以智能的加载 META-INF/spring.factories 配置文件中注册的各种 XxxAutoConfiguration 类。
  • 当某个 XxxAutoConfiguration 类满足其注解 @Conditional 指定的生效条件时,实例化该 XxxAutoConfiguration 类中定义的 Bean 注入 Spring 容器,就可以完成依赖框架的自动装配。

1. Spring Boot 源码剖析

Spring Boot应用启动时会调用 SpringApplication.run(String... args) 方法。

run 方法内部会调用 refreshContext(context) 方法来完成自动装配的操作。

跟剥洋葱一样,通过 debug 的方式一层层往里跟,最终会调用ConfigurationClassParser 类来完成所有配置类的解析,其所有的解析逻辑在 parser.parse(candidates) 方法中。

调用重载的 parse 方法来完成解析。

接着调用 processConfigurationClass 方法来完成配置类解析处理。

接着调用 doProcessConfigurationClass 方法,此方法是支持注解配置的核心逻辑处理,方法内部会调用 processImports(configClass, sourceClass, getImports(sourceClass), filter, true) 方法进行递归解析,获取导入的配置类(@Import)。

接着看看获取配置类的相关逻辑,此时会看到所有的 bean 都以导入的方式被加载进去。

继续 Debug,会调用 ConfigurationClassParser 中的 parse 方法中的最后一行,继续跟进 this.deferredImportSelectorHandler.process() 方法。

继续 Debug,会调用 DeferredImportSelectorHandler 的 process 方法。

继续 Debug,会调用 DeferredImportSelectorGroupingHandler 的 processGroupImports 方法。

processGroupImports() 内部,会调用 grouping.getImports() 方法。

grouping.getImports()方法内部会调用 this.group.process方法。

this.group.process 方法可以说是自动装配的重点了。

getAutoConfigurationEntry 方法详细解释一下

代码语言:javascript
复制
/**
 * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
 * of the importing {@link Configuration @Configuration} class.
 * @param annotationMetadata the annotation metadata of the configuration class
 * @return the auto-configurations that should be imported
 */
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   // 通过 SpringFactoriesLoader 类提供的方法加载类路径中的 META-INF 目录下的 
   // spring.factories 文件中针对 EnableAutoConfiguration 的注册配置类
   List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
   // 对获得的注册配置类集合进行去重处理,防止多个项目引入同样的配置类
   configurations = removeDuplicates(configurations);
   // 获得注解中被 exclude 或 excludeName 所排除的类的集合
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   // 检查被排除类是否可实例化,是否被自动注册配置所使用,不符合条件则抛出异常
   checkExcludedClasses(configurations, exclusions);
   // 从自动配置类集合中去除被排除的类
   configurations.removeAll(exclusions);
   // 检查配置类的注解是否符合 spring.factories 文件中 AutoConfigurationImportFilter 指定的注解检查条件
   configurations = getConfigurationClassFilter().filter(configurations);
   // 将筛选完成的配置类和排查的配置类构建为事件类,并传入监听器。监听器的配置在于 spring.factories 文件中
   // 通过 AutoConfigurationImportListener 指定
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}

能够发现getCandidateConfigurations 方法中会通过 SpringFactoriesLoader 类来加载类路径中的 META-INF 目录下的 spring.factories 文件中针对 EnableAutoConfiguration 的注册配置类。

为了调试方便,在源码中的 process 方法上里加入了打印输出。

运行后,此时控制台输出如下。

代码语言:javascript
复制
AutoConfigurationImportSelector.AutoConfigurationGroup.process() , entries = {
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration=smoketest.simple.SampleSimpleApplication, 
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration=smoketest.simple.SampleSimpleApplication
}

2. 例行回顾

本文采取 Debug 的方式跟了一下 Spring Boot 自动装配的源码,旨在感受一下自动装配的实现方式,其实这种自动装配的思想,在开发轮子时或许能够借鉴一下,会对轮子的扩展带来质的改变。

为了方便记忆,把 Spring Boot 自动装配繁琐的流程抽象一下。

另外 Spring Boot 自动装配源码 Debug 主线,感兴趣可以自行跟一下源码。

一起聊技术、谈业务、喷架构,少走弯路,不踩大坑,会持续输出更多精彩分享,敬请期待!

参考资料:

https://spring.io/

https://start.spring.io/

https://spring.io/projects/spring-boot

https://github.com/spring-projects/spring-boot

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/

https://stackoverflow.com/questions/tagged/spring-boot

《Spring Boot实战》《深入浅出Spring Boot 2.x》

《一步一步学Spring Boot:微服务项目实战(第二版)》

《Spring Boot揭秘:快速构建微服务体系》

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一猿小讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档