1. 前言

SpringBoot是目前软件中最主流的框架,无论是工作还是面试基本都有它的身影,SpringBoot主要解决了传统spring的重量级xml配置Bean,实现了自动装配;所以,我们也常在面试中被问到SpringBoot是如何实现自动装配。

本篇文章会从springboot源码进行自动装配的原理解析,并总结面试如何简洁的描述

2. 源码解析
我们以springboot 2.2.5.RELEASE版本进行解析

2.1 @SpringBootApplication源码解析

先看看springboot启动注解@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 {@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")String[] scanBasePackages() default {};@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")Class<?>[] scanBasePackageClasses() default {};@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;}

可以看出@SpringBootApplication是由三个注解组成的,@ComponentScan注解则是spring原生注解,其作用是扫描启动类所在的包以及子包所有Bean组件并注册到IOC容器中,两外两个我们再看看源码

@SpringBootConfiguration源码:

@EnableAutoConfiguration源码:

总结@SpringBootApplication注解由三个注解共同完成自动装配,各个注解作用如下

@SpringBootConfiguration: 标记启动类为一个spring配置类
@EnableAutoConfiguration: 实现自动装配的核心注解(重头戏)
@ComponentScan: 扫描启动类所在的包以及子包下所有标记为Bean的组件并注册到IOC容器中

2.2 @EnableAutoConfiguration源码解析

@EnableAutoConfiguration注解才是实现自动装配的核心注解,上面看了他的源码是通过@Import注解导入AutoConfigurationImportSelector类,我们来看看AutoConfigurationImportSelector源码:

通过源码可知,AutoConfigurationImportSelector是ImportSelector的一个字类,@Import注解的一大用处就是导入一个ImportSelector类,通过selectImports方法返回所有需要被注册为bean的类全名的数组集合,具体可以参考我们的上一篇文章@Import注解的详解

我们再来看看AutoConfigurationImportSelector类的selectImports方法

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {// 判断自动装配开关是否打开if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

首先通过 isEnabled 方法判断自动装配开关是否打开,这里就不细讲了,我们从后面两步开始分析

2.2.1. AutoConfigurationMetadataLoader.loadMetadata() 方法源码分析:

loadMetadata() 方法源码:

META-INF/spring-autoconfigure-metadata.properties文件内容属性:


PropertiesLoaderUtils的 loadProperties 方法源码:


最后创建并返回的AutoConfigurationMetadata对象

综合上述可以得出 AutoConfigurationMetadataLoader.loadMetadata() 方法是用来读取spring-boot-autoconfigure依赖下的
spring-autoconfigure-metadata.properties配置文件内容并封装成一个 AutoConfigurationMetadata 对象

2.2.2 getAutoConfigurationEntry 方法源码分析(重点)

// getAutoConfigurationEntry 方法源码
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {// 再次判断自动装配开关是否打开if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}// 获取 @EnableAutoConfiguration注解的 exclude 和 excludeName 属性AnnotationAttributes attributes = getAttributes(annotationMetadata);// 获取该依赖下的 spring.factories配置文件的内容List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 移除重复的数据configurations = removeDuplicates(configurations);// 获取spring.autoconfigure.exclude 配置文件的内容并与exclude 和 excludeName 属性合并到一个集合中Set<String> exclusions = getExclusions(annotationMetadata, attributes);// 检验configurations中需要排除的内容checkExcludedClasses(configurations, exclusions);// 移除configurations中需要排除的内容configurations.removeAll(exclusions);// 再次对configurations中的内容进行过滤configurations = filter(configurations, autoConfigurationMetadata);// 关闭spring监听器中的自动装配事件fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}

首先依然通过 isEnabled 方法判断自动装配开关是否打开,这里就不细讲了,我们从后面开始分析

getAttributes方法就是获取 @EnableAutoConfiguration注解的 exclude 和 excludeName 属性,由于启动类默认并未设置这两个属性,这里就不再深入分析

getCandidateConfigurations方法源码分析(重点)

1. SpringFactoriesLoader.loadFactoryNames方法源码:

2. spring.factories配置文件

3. getCandidateConfigurations方法最终返回的结果

removeDuplicates(configurations): 字面上就可以看出是去除重复的元素

getExclusions源码分析:

此操作就是将exclude和excludeName属性内容绑定到环境变量去中,由于这两个属性默认为空所以略过

checkExcludedClasses(configurations, exclusions): 方法名上可以知道该方法是检查configurations内容中哪些是需要排除的,由于exclusions默认为空,这里实际没做什么有效的操作,所以不再深入分许

configurations.removeAll(exclusions): 方法名上可以看出是移除需要排除的元素

filter(configurations, autoConfigurationMetadata) 方法源码分析(重点):

fireAutoConfigurationImportEvents(configurations, exclusions): 关闭spring监听器中的自动装配事件

new AutoConfigurationEntry(configurations, exclusions): 最终的返回的结果


综合上述 @EnableAutoConfiguration 注解通过@Import注解导入 ImportSelector 的子类 AutoConfigurationImportSelector 类,该类通过selectImports方法加载读取所有 spring-boot-autoconfigure 依赖下的 spring-autoconfigure-metadata.properties 配置文件和spring.factories 配置文件的内容,并根据 AutoConfigurationImportSelector 类下的 AutoConfigurationImportFilter过滤器的过滤规则和 spring-autoconfigure-metadata.properties 配置文件的内容过滤掉 spring.factories文件中需要被过滤掉的组件元素(当然这之前还有一步根据@EnableAutoConfiguration注解的 exclude 和 excludeName属性过滤 spring.factories 配置文件的内容,由于 @EnableAutoConfiguration注解的这两个属性默认为空,所以这步操作什么都没做),最终返回spring.factories文件中剩余组件的类全名数组,并由IOC容器注册为Bean

3. 总结
以上解析了springboot实现自动装配的源码,实际上我们在工作中基本用不到,只需了解即可,我们可能在面试中经常会被问到自动装配的原理,按照以上的解析,这里我们总结一下,面试可以这样简洁回答:
启动类的@SpringBootApplication注解由@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan三个注解组成,三个注解共同完成自动装配;

@SpringBootConfiguration 注解标记启动类为配置类
@ComponentScan 注解实现启动时扫描启动类所在的包以及子包下所有标记为bean的类由IOC容器注册为bean
@EnableAutoConfiguration通过 @Import 注解导入 AutoConfigurationImportSelector类,然后通过AutoConfigurationImportSelector 类的 selectImports 方法去读取需要被自动装配的组件依赖下的spring.factories文件配置的组件的类全名,并按照一定的规则过滤掉不符合要求的组件的类全名,将剩余读取到的各个组件的类全名集合返回给IOC容器并将这些组件注册为bean

springboot自动装配原理相关推荐

  1. 【理解springboot自动装配原理】

    理解springboot自动装配原理: 最近读了小马哥(mercyblitz)Springboot编程思想(核心篇),有了一些心得和感悟,分享给大家: 1. 官网介绍了激活自动装配的方法: * 文档提 ...

  2. SpringBoot自动装配原理浅析

    Springboot自动装配原理 SpringBoot是当下J2EE最为流行的框架,它有着轻量,快捷等特点,让程序员们可以专注在业务逻辑的编写上,而不用花太多的力气在一些环境的配置,整合组件的配置上面 ...

  3. 面试终极宝典:Springboot自动装配原理

    Springboot的自动装配过程,网上大多都是罗列代码,即使看完了,也还存在很多的疑点.下面,这是我总结的在面试过程中介绍SpringBoot自动装配原理的话术,拿来即用就可. Springboot ...

  4. 刨析 SpringBoot 自动装配原理,其实很简单

    J3 SpringBoot # 源码 # 自动装配 一日我在愉快得遨游时,看到有鱼友在问:SpringBoot 中引入了 Nacos 依赖为啥就可以直接使用 Nacos 中的相关功能呀! 认真思考了一 ...

  5. 淘宝(SpringBoot自动装配原理)

    什么是 SpringBoot 自动装配 通过注解或者一些简单的配置就能在 Spring Boot 的帮助下实现某块功能 SpringBoot 是如何实现自动装配的 SpringBoot 的核心注解 S ...

  6. springboot自动装配原理笔记一

    思维导图 太长放不了截图,就看大纲吧. 从启动类的@SpringBootApplication注解开始,探究其自动装配的原理 结论 整合javaEE,解决方案和自动装配的东西都在spring-boot ...

  7. SpringBoot 自动装配原理

    运行原理探究 我们之前写的HelloSpringBoot,到底是怎么运行的呢,Maven项目,我们一般从pom.xml文件探究起: 1.父依赖 pom.xml spring-boot-dependen ...

  8. SpringBoot 自动装配原理解析

    自动装配是 Spring Boot 的核心部分,也是 Spring Boot 功能的基础,正是由于自动装配,才 将我们从 Bean 的繁复配置中解脱出来.那么 Spring Boot 中的自动装配指的 ...

  9. SpringBoot自动装配原理解析——面试可以这样会回答

    1. 前言 SpringBoot是目前软件中最主流的框架,无论是工作还是面试基本都有它的身影,SpringBoot主要解决了传统spring的重量级xml配置Bean,实现了自动装配:所以,我们也常在 ...

  10. 面试题总结(mybatis一级缓存及二级缓存、springboot自动装配原理等)

    1.mybatis一级缓存及二级缓存 区别: 一级缓存的作用域是一个sqlsession内: 二级缓存作用域是针对mapper(Namespace)进行缓存: 一级缓存: 在参数和SQL完全一样的情况 ...

最新文章

  1. 工具分享 --- 分享一个在线制作ico的网站
  2. 【CF 1191】Tokitsukaze, CSL and Stone Game//Tokitsukaze and Duel//Tokitsukaze and Strange Rectangle
  3. sql server链接查询
  4. java文件操作和_JAVA文件操作类和文件夹的操作
  5. 语音识别现状与工程师必备技能
  6. n分解后的最大乘积java_【编程题】乘积最大的拆分
  7. TestNG执行测试方法依赖关系
  8. shell 学习之if语句
  9. C盘文件分析(如何减小C盘容量)
  10. 微信nickname乱码 php,CSV中微信名字乱码 问题
  11. Linux资源管控【笔记】
  12. 如何根据公司名称来筛选快递
  13. SSH所选用户密钥为在远程主机上注册。请再试一次
  14. 用Python写一个企业微信自动化打卡的脚本
  15. 《Windows 8 权威指南》——2.7 降低功耗,延长续航时间才是王道
  16. 论文阅读-Boosting Data-driven Evolutionary Algorithm with Localized Data Generation
  17. 2018年90后薪资报告出炉:看看你被甩了多远!
  18. 未来可期的6个物联网发展
  19. 【项目经验】Java web 页面跳转中文乱码
  20. pdf转换成txt转换器的操作方法

热门文章

  1. java蓝宇快递打印系统_蓝宇快递打印系统
  2. DAPLink-Firmware
  3. Bypassing JavaScript Filters – the Flash! Attack
  4. VirtualBox调整分分辨率
  5. linux系统下使用uTorrent下载ipv6资源
  6. 教你用优化视频的方法提高视频的质量
  7. 用Python验证指数基金定投策略
  8. 关于什么是AndroidX(一)
  9. 《改变心理学的40项研究》第二章 知觉与意识
  10. 名将戚继光与北蒙之战