首页 > 编程语言 >SpringBoot学习(9)(springboot自动配置原理)(源码分析、面试题)

SpringBoot学习(9)(springboot自动配置原理)(源码分析、面试题)

时间:2024-09-08 13:51:05浏览次数:11  
标签:面试题 这个 SpringBoot 配置文件 配置 Bean 源码 自动 注解

目录

一、引言

二、为啥学习自动配置原理?

三、自动配置

(1)基本概述

(2)学习回顾

四、自动配置——源码分析

(1)回顾学习

(2)回到源码学习

(1)注解@ComponentScan

(2)注解@SpringBootConfiguration

(3)核心注解@EnableAutoConfiguration

(4)对刚刚源码的一个大致总结(梳理)

五、解决问题

六、分析总结

(1)小总结

(2)面试(总结)

一、引言

  • 之前学习了Bean的扫描、Bean的注册、以及Bean的注册条件。
  • 现在在这篇博客学习springboot的自动配置原理。

二、为啥学习自动配置原理?

  • 在实际的开发中,经常会定义一些公共的组件,供大家一起使用。为了使用更加的方便,经常会将这些公共的组件自定义成starter。如果想定义starter,就必须先了解自动配置原理才可以。
  • 应对面试。springboot作为当下市面上最流行的Java技术之一。面试题:请说一下springboot自动配置的原理?

三、自动配置

(1)基本概述
  • 所谓的自动配置。就是遵循约定大约配置的原则,在boot程序启动后,起步依赖中的一些bean对象会自动注入到ioc容器中。
(2)学习回顾
  • 之前学习bean扫描、bean注册、bean注册条件的时候——>其中学习的案例中通过导入一个自定义的jar包,jar包中有两个实体类(Country、Province),然后在自己的boot工程引入了这个jar包。想把Country和Province注入到Ioc容器当中——>自己提供写了一个配置类(CommonConfig),这里面提供了两个方法(country()、province())这两个方法分别用来注入Country对象、Province对象——>最后在启动类中使用注解@Import把这个配置类给导入进来——>这样就注入到Ioc容器当中了——>可是真的是自动配置了吗??

  • 之前学习springboot整合mybatis的时候,只用引入mybatis的起步依赖就行了,不用去手动的注入对应的bean对象(自动注入到Ioc容器当中),并没有写任何的配置

四、自动配置——源码分析

(1)回顾学习
  • 当程序引入 "spring-boot-starter-web" 起步依赖,启动后。会自动往Ioc容器中注入DispatcherServlet类
  • 验证是不是如上所说?
  • 首先pom文件中并没有引入web依赖(只引入了一个springboot的核心起步依赖)


  • 回到启动类。将程序启动后,将返回的Ioc容器接收一下。使用ApplicationContext context = SpringApplication.run(SpringbootAutoConfigApplication.class,args);然后用这个context对象调用方法getBean(String name),里面的name参数写上面要测试的类"dispatcherServlet"。然后把他打印输出到控制台。

  • 因为没有引入web的起步依赖,所以Ioc容器中并没有该指定类的对象。报错

  • 重新导入完web的起步依赖后(别忘了刷新一下Maven)再重新运行。发现获取成功!这就验证了只要引入web的起步依赖,它就会自动的往Ioc容器里面注入一个叫"dispatcherServlet"。springboot是如何做到的??


(2)回到源码学习
  • 从启动类的@SpringBootApplication开始(这里之前学习Bean扫描时看到过)(鼠标停留在那,然后按ctrl进入到源码界面)
  • 进去之后可以看到,注解@SpringBootApplication是一个组合注解,它组合了三个注解,如下:

(1)注解@ComponentScan

其中第三个注解@ComponentScan之前学习过,就是Bean扫描。(springboot默认只能扫描启动类所在的包及其子包。其它地方扫描不到。若想要扫描其它的包,可以手动的去添加注解@ComponentScan)


(2)注解@SpringBootConfiguration

(按住ctrl点进去)说明我们的启动类也是一个配置类??

(3)核心注解@EnableAutoConfiguration
  • 当看到这个@EnableXXX的时候,回想起之前学习注解@Import的时候,用更优雅的方式写进代码,使用组合注解——>@Enable+配置类名

(按住ctrl点进去)组合了两个注解


  • 重点关注@Import(导入注解)那行的注解。发现很熟悉"ImportSelector"。因为注解@Import经常导入两种类——>配置类、ImportSelector接口实现类


  • 现在再按住CTRL点击进来,再看到它实现"DeferredImportSelector"这个接口

  • 现在再按住CTRL点击进来,看这个接口它继承了"ImportSelector"这个接口。也就是说我们当前这个类"AutoConfigurationImportSelector"它是实现"ImportSelector"这个接口,那么必然会重写方法"selectImports()"

  • 例如之前案例学习的下面这种写法

  • 之前说过selectImports()方法,会被我们的springboot自动调用,从而得到它返回的全类名的字符串数组,把对应的类的Bean对象注入到Ioc容器里。

  • 然后之前在selectImports()方法中,返回的全类名,我们并没有"写死",而是从配置文件中读取。在return返回回去。现在继续向下看,首先它return的是一个对象调用返回值,然后将其转换为字符串数组。现在核心就在"autoConfigurationEntry"这个对象上。

  • 因此需要猜想,这个方法getAutoConfigurationEntry()里面肯定要知道配置文件在哪里。然后现在跟踪这个方法——>返回的是一个新(new)的对象——>其中两个参数:
    "configurations"跟我们的配置相关

  • 然后又跟getCandidateConfigurations()方法有关,再继续跟进——>它调用了一个.load()方法,这是不是加载的意思。而且它后面的参数是一个类名"AutoConfiguration",后面会继续看到。往后再跟进就很复杂,先到这里继续看。
  • 其次还能往下看到底下有一段断言——>它是说:"这个configurations不能为空",如果为空了就出现下面的提示!!——>重点看下面的提示:"在这个METC-INF目录下的spring文件中有一串很长的配置文件.imports",以后将这个配置文件称为"dear imports配置文件"

  • 接着我们去寻找上面所说的配置文件。回到pom文件,当时引入了一个springboot的核心起步依赖。按住ctrl进去——>

  • 进入之后可以看到autoconfigure,顾名思义就是自动配置的意思

  • 接着来到左边查看第三方库,找到上面的autoconfigure,然后看到上面的目录METC-INF——>spring目录——>对应的"dear imports"配置文件——>打开看到之后全是一些全类名,程序会从里面读取,然后使用——>然后在配置文件中ctrl+f(搜索其中一个类名"DispatcherServletAutoConfiguration")这个类是不是很熟悉,之前引入web起步依赖,它会自动注入类"DispatcherServlet"的Bean对象进入Ioc容器——>接着我们点击进去看看——>这个类添加一个注解@AutoConfiguration,顾名思义就是自动配置的意思——>再点进去就看到它也是一个组合注解!——>其中有一个注解@Configuration,说的明白一点就是说明前面"DispatcherServletAutoConfiguration"这个类就是一个配置类,然后用上注解@AutoConfiguration就是为了完成自动配置的——>然后下面还有一个注解@ConditionalOnClass,这个是不是很熟悉(在bean注册条件里的),它在这的意思就是如果环境里面有"DispatcherServlet"这个类,这个时候这个自动配置类"DispatcherServletAutoConfiguration"起效果,将来就会自动的注入一个"DispatcherServlet"对象,如果环境里面没有,自动配置类就不生效,不注入了——>接着它里面还提供了一个内部的配置类。这个类里面提供了一个重要的方法——>方法的返回值类型是"DispatcherServlet"。方法的内部new了一个"DispatcherServlet"对象,而且这个方法添加了一个@Bean注解,而我们现在发现这个方法和之前自己的操作没什么区别!!——>就是都是声明一个方法,然后再声明一个注解@Bean——>而这个地方最核心的地方就是:它让这个类"DispatcherServletAutoConfiguration"放在指定的配置文件中,然后springboot就能够自动的读取到这个全类名,然后把这个配置类的对象注入到Ioc容器当中,而这个配置类当中还有一个配置类,而且内部的配置类中还有一些方法并添加注解@Bean,所以springboot它会自动的继续解析,直到把这些@Bean所注解的方法全部解析到,执行这些方法,把返回值注入到Ioc容器当中——>所以我们自动配置的核心就再这个配置文件当中!!!——>源码分析查看到这里吧。







(4)对刚刚源码的一个大致总结(梳理)
  • 从刚刚开始——>我们是从注解@SpringBootApplication开始的,它是一个组合注解,它组合了一个非常重要的注解@EnableAutoConfiguration,开启自动配置——>而这个@EnableAutoConfiguration也是一个组合注解,它组合了@Import注解,导入了一个"AutoConfigurationImportselector"这个类,这个类是"Importselector"的实现类,所以它里面重写了一个selectImports()方法,这个方法内部通过层层调用,会读取一个配置文件——>是一个xxx.spring.imports配置文件,在这个配置文件中,写了很多的全类名——>这些类都是自动配置类,其中有一个类"DispatcherServletAutoConfiguration",它是完成"DispatcherServlet"类Bean对象的自动注入的——>这个类"DispatcherServletAutoConfiguration"添加了两个注解,第一个是注解@AutoConfiguration,标识当前这个类是一个自动配置类。第二个是注解@Conditional0nClass,这个是标识用来设置Bean的注册条件,如果环境中有类"DispatcherServlet",那么这个自动配置类就自动生效,否则不生效——>也就是当引入了web起步依赖之后,我们的springboot就会帮忙自动的将一个类"DispatcherServlet"的bean对象注入到Ioc容器中——>而自动注入的代码核心就在底下,写了一个方法,方法的返回值类型就是类"DispatcherServlet",这个方法的返回值声明了一个注解@Bean。

  • 说了这么多,自动配置的核心就是在这个".imports"配置文件当中。也就是在面试当中提到这个文件,就答案已经正确了一半了。但是在网络很多文章当中,把这个文件叫做"spring deer factories",因为在以前springboot的版本用的是其它的配置文件名。

五、解决问题

(1)前面提到的案例中是否自动配置问题??之前写的代码并没有达到自动配置的效果,因为需要手动的提供一个配置类,然后写注解@Import,这样很麻烦。如果想要自动达到配置的效果,那么这个配置类就不应该自己去提供!也就是谁提供下面的Bean对象,就提供这个配置类

  • 也就是"CommonConfig"这个配置类,要让第三方jar包提供
  • 然后还要提供应该自动配置类"CommomAutoConfig",并且在这个自动配置类上添加两个注解。分别是@AutoConfiguration它用来标识这个类是一个自动配置类、通过@Import注解把这个配置类"CommonConfig"导入进来,然后需要提供一个配置文件".imports",在这个配置文件中,把这个"CommomAutoConfig"自动配置类的全类名给它写入,具体图片操作如下展示:

  • 开始演示如何实现自动配置操作
  • 首先安装好对应的jar包,里面的代码已经基本写好

  • 接着安装到Maven的本地仓库
  • 接着在pom文件中手动的添加对应的依赖(common-pojo)完毕之后记得刷新Maven

  • 然后去查看对应库里安装的jar包(2.0版本的)

  • 继续查看里面的内容(配置类、自动配置类)
  • 自动配置类里用到两个注解@AutoConfiguration(标识当前是自动配置类)、@Import(把我们的"CommonConfig"这个配置类导入进来,也就是当springboot读取到这个自动配置类的时候,它就会读取到注解@Import,从而间接的读取到"CommonConfig"这个配置类)


  • 仿照之前在源码看到的——>在对应的目录下提供了一个配置文件"xxx.imports"

  • 在".imports"文件当中写了自动配置类的对应的全类名

  • 回到启动类,是否能够测试成功??打印getBean("province"),看是是否"Province"类的Bean对象已经能够自动的注入成功了。成功了!

  • 现在可以把启动类的@Import去掉了,因为能够自动配置了

六、分析总结

(1)小总结
  • 通过源码分析,可以看到springboot自动配置无非就是提供一个自动配置类,然后把这个类名写到指定的配置文件里边。
(2)面试(总结)

标签:面试题,这个,SpringBoot,配置文件,配置,Bean,源码,自动,注解
From: https://blog.csdn.net/m0_74363339/article/details/141998533

相关文章

  • 【2025】基于springboot二手闲置物品置换平台(源码+文档+调试+答疑)
    ......
  • Java计算机毕业设计医生诊疗系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在医疗资源日益紧张与患者需求日益增长的双重背景下,传统医疗模式面临着诸多挑战,如就诊流程繁琐、信息孤岛现象严重、医患沟通不畅等。随着信息技术的......
  • Java计算机毕业设计消防志愿者服务系统的设计与实现(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着城市化进程的加速和社会对公共安全需求的日益增长,消防工作的重要性日益凸显。然而,消防力量的不足与复杂多变的火灾形势之间存在着明显的矛盾。在......
  • Java计算机毕业设计疫情防控打卡(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在全球新冠疫情持续蔓延的背景下,高校作为人群密集、流动性大的场所,其疫情防控工作显得尤为重要。传统的疫情防控手段,如人工统计健康状况、追踪行程信......
  • Java计算机毕业设计心理测评系统的设计与实现(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在快节奏的现代生活中,心理健康问题日益凸显,成为影响个体生活质量和社会稳定的重要因素。随着社会对心理健康关注度的提升,传统的心理咨询服务已难以满......
  • Java计算机毕业设计学生社团信息管理系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在高等教育日益普及的今天,学生社团作为校园文化的重要组成部分,不仅丰富了学生的课余生活,还促进了学生综合素质的全面发展。然而,随着社团数量的增多和......
  • Java计算机毕业设计线上学习系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展和互联网的普及,教育领域正经历着前所未有的变革。传统面对面教学模式虽有其不可替代的优势,但在灵活性、覆盖范围及个性化学习......
  • Java计算机毕业设计医院预约挂号系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着医疗需求的日益增长与医疗资源分配的不均衡,传统就医模式中的挂号难、排队久等问题日益凸显,成为影响患者就医体验与医疗效率的重要因素。信息技术......
  • Java计算机毕业设计物业管理系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着城市化进程的加速,住宅小区作为城市的重要组成部分,其管理与服务质量直接关系到居民的生活品质与幸福感。然而,传统物业管理方式普遍存在着信息不透......
  • Java计算机毕业设计校内二手交易平台(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高等教育的普及与校园生活的日益丰富,学生群体中的物品更新换代速度加快,从学习资料到生活用品,大量闲置物品亟待有效流转。传统的校园跳蚤市场受限......