Springboot自动配置原理+面试回答

本文涉及的产品
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
简介: 理解springboot自动装配首先要理解什么是约定优于配置,它的设计目的是用来简化spring应用的初始化搭建以及开发过程,从而使开发人员不在需要定义样板化的配置,按照约定进行编程,是一种软件设计范式

springboot自动配置面试相关内容在文章最后,小伙伴根据选择观看哦

前言:理解springboot自动装配首先要理解什么是约定优于配置,它的设计目的是用来简化spring应用的初始化搭建以及开发过程,从而使开发人员不在需要定义样板化的配置,按照约定进行编程,是一种软件设计范式

首先springboot整合的每一个技术点都会对应着两个类一个是XXXProperties,另一个是XXXAutoConfiguration

XXXAutoConfiguration:帮我们实例化一些组件

XXXProperties:在我们实例化的过程中可能需要一些值,那么就在这个类里给他赋值

拿Mybatis来说,我们只需要导入mybatis的starter在经过简单的配置就可以使用了,

我们可以搜索一个类叫MybatisProperties,这里是springboot帮我们注入属性值,也就是依赖注入,而我们只需要配置必要的信息就可以使用,是因为springboot采用约定大于配置,我们只需要去修改我们需要的那一部分就可以了

然后在看到MybatisAutoConfiguration,首先他有一个注解@Configuration所以他是一个配置类,这个类的主要作用就是帮我们实例化一些组件

在这个文件里都是springboot主动整合的第三方技术所对应的XXXAutoConfiguration类,也就是这个类的全限定名, 然后通过反射的原理就是class.forname来新建这个对象

接下我们来看怎么读到这个这个文件,这个时候来看到主启动类的核心注解:

而核心的注解分别是

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan

对于@ComponentScan这个注解还是比较核心的,需要重点理解一下,它是来自于spring框架的一个注解,作用是对指定的package进行扫描,找到其中符合条件的类,默认是搜索被@Component所修饰的配置类,也可以通过指定属性来指定要进行扫描的package,也就是扫描我们的controller等,而他是怎么扫描到的呢,就是根据我们的@EnableAutoConfiguration注解,这个注解点进去有一个@AutoConfigurationPackage

这个继续点进去有一个注册器Registrar

通过这个注册器我们就可以找到当前类所在的包

现在来看一下在MET-INF下的spring.factories是怎么加载的,现在我们还是看到@EnableAutoConfiguration这个注解,这个注解下又导入了一个类@Import({AutoConfigurationImportSelector.class})

简单理解一下@Import:是来自spring框架的一个注解,作用是显示的从其他地方加载配置类的方式,这样可以避免使用性能较差的组件进行扫描

然后继续来看AutoConfigurationImportSelector.class的作用,这个翻译过来的意思为自动配置导入选择器

我们都知道,如果这个类实现了ImportSelector接口,那他肯定重写了一个方法就是selectImports方法,而在这个类里也不例外,这个类里确实有这个方法

他通过getAutoConfigurationEntry来进行导入,我们继续点进去

而这个getCandidateConfigurations方法的返回值是string,而这个方法就是真正帮我们去读到那个spring.factories配置文件

这个集合真正读取到了我们spring.factories所有的自动配置类,而这里面也默认加载了redis的内容,既然加载了redis我们又没导包,那他为什么不报错呢

这个取决于@ConditionalOnClass,这个注解通俗的说就是Spring工程中引用了redis的包 才会构建这个bean,就是说只有在classpath下能找到redisTemplate类才会构建这个bean。

简单理解,加了这个注解的类不一定会生效,只有这个注解里面指定的那个类存在,那么他才会生效,如果不存在那么这个类就不生效,也就是说我们刚刚在getCandidateConfigurations读取到的130多个配置类并没有全部被加载,只是加载了我们引入了依赖的类

因此我们的redistemplate就不需要我们自己new对象了,而是通过ioc控制反转进行外部注入,而stringRedisTemplate是经过序列化后的对象,因为不序列化默认走的是JDK的序列化器,那样存入redis的结果不仅占用内存较高而且不容易阅读

在这里我们就可以发现只要我们导了redis的启动器,我们就不需要配太多的东西就可以使用了

在RedisProperties这个类里,就是我们常用的配置,而默认的host地址是localhost,因此我们只要windows本地启动了redis,我们不需要任何配置文件,就可以使用redis,这样就基本完成我们的自动装配了

继续看回来springboot拿到我们从spring.factories读取的这个集合后到 ImportAutoConfigurationImportSelector的determineImports方法,然后在这里又把这个集合包装成一个set集合,作用是为了去重

然后在这通过各种校验过滤

最后返回一个AutoConfigurationEntry

在这里就是通过@ConditionalOnClass来进行排除过滤

再到这个方法内,他利用String工具类转成一个数组,返回给spring容器,然后再利用类加载器,通过Class.fornaame也就是通过反射的方式帮我们实例化,实例化完成之后帮我们放到IOC容器里

简单来讲:就是通过springboot的核心注解里的选择器,而这个选择器会加载我们的spring.factories文件,拿到这些文件之后通过反射生成对象,在反射生成的时候要先判断我们有没有导包,如果没导包就不生成,导包了就生成,然后通过XXXProperties给属性赋值,没有的我们就需要在yml中自己配置

面试话术:

主配置类启动,通过@SringBootApplication 中的@EnableAutoConfguration 加载所需的所 有自动配置类,然后自动配置类生效并给容器添加各种组件。那么@EnableAutoConfguration 其实是通过它里面的@AutoConfigurationPackage 注解,将主配置类的所在包皮下面所有子包 里面的所有组件扫描加载到 Spring 容器中; 还通过@EnableAutoConfguration 里面的 AutoConfigurationImportSelector 选择器中的 SringFactoriesLoader.loadFactoryNames()方法,获取类路径下的 META-INF/spring.factories 中的 资源并经过一些列判断之后作为自动配置类生效到容器中,自动配置类生效后帮我们进行自 动配置工作,就会给容器中添加各种组件:这些组件的属性是从对应的 Properties 类中获取 的,这些 Properties 类里面的属性又是通过@ConfigurationProperties 和配置文件绑定的:所以 我们能配置的属性也都是来源于这个功能的 Properties 类。SpringBoot 在自动配置很多组件 的时候,先判断容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置 的,如果没有,才自动配置;如果有些组件可以有多个就将用户配置和默认配置的组合起来

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
30天前
|
JavaScript 前端开发
【Vue面试题二十五】、你了解axios的原理吗?有看过它的源码吗?
这篇文章主要讨论了axios的使用、原理以及源码分析。 文章中首先回顾了axios的基本用法,包括发送请求、请求拦截器和响应拦截器的使用,以及如何取消请求。接着,作者实现了一个简易版的axios,包括构造函数、请求方法、拦截器的实现等。最后,文章对axios的源码进行了分析,包括目录结构、核心文件axios.js的内容,以及axios实例化过程中的配置合并、拦截器的使用等。
【Vue面试题二十五】、你了解axios的原理吗?有看过它的源码吗?
|
29天前
|
安全 Java 容器
【Java集合类面试二十七】、谈谈CopyOnWriteArrayList的原理
CopyOnWriteArrayList是一种线程安全的ArrayList,通过在写操作时复制新数组来保证线程安全,适用于读多写少的场景,但可能因内存占用和无法保证实时性而有性能问题。
|
30天前
|
JavaScript 前端开发
【Vue面试题二十七】、你了解axios的原理吗?有看过它的源码吗?
文章讨论了Vue项目目录结构的设计原则和实践,强调了项目结构清晰的重要性,提出了包括语义一致性、单一入口/出口、就近原则、公共文件的绝对路径引用等原则,并展示了单页面和多页面Vue项目的目录结构示例。
|
5天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
5天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
15天前
|
消息中间件 Java 编译器
面试官:说说Lambda表达式底层原理?
面试官:说说Lambda表达式底层原理?
18 2
面试官:说说Lambda表达式底层原理?
|
6天前
|
Java 开发者 数据格式
【Java笔记+踩坑】SpringBoot基础4——原理篇
bean的8种加载方式,自动配置原理、自定义starter开发、SpringBoot程序启动流程解析
【Java笔记+踩坑】SpringBoot基础4——原理篇
|
30天前
|
存储 缓存 JavaScript
【Vue面试题十八】、你知道vue中key的原理吗?说说你对它的理解
这篇文章详细介绍了Vue中的`keep-alive`组件,解释了其作用是缓存不活动的组件实例以避免重复渲染DOM,并阐述了`keep-alive`的使用场景、props属性配置、以及如何通过源码理解其缓存机制和原理。
【Vue面试题十八】、你知道vue中key的原理吗?说说你对它的理解
|
29天前
|
Java
【Java集合类面试二十一】、请介绍TreeMap的底层原理
TreeMap基于红黑树实现,能够根据键的自然顺序或提供的Comparator排序,其基本操作的时间复杂度为O(log N)。
|
29天前
|
Java
【Java集合类面试二十】、请介绍LinkedHashMap的底层原理
LinkedHashMap的底层原理是在HashMap的基础上,通过维护一条双向链表来保持键值对的插入和遍历顺序,同时继承HashMap的多数方法并重写部分方法以维护链表。