【SpringBoot】自动配置自动加载controller的原理

SpringBoot自动配置&&自动加载controller的原理.md

好久没有更新自己的博客了,自己最近的正好有点空闲的时间进行,自己在写着写着,突然想起来,

为什么我们点击application就能自动加载@Controller呢?(好家伙,我顿时鱼鳃,哈哈)

1.首先我们来到启动现场===>启动类

@SpringBootApplication
public class TestApplication extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(ActAfterApplication.class);}public static void main(String[] args) {SpringApplication.run(ActAfterApplication.class, args);}
}

我们会看到在TestApplication启动类上会有一个注解:@SpringBootApplication

这个注解,就是我们今天的文章的核心,核心**,核心**!!!=====>你可能会说,我问怎么加载@Controllerd的,你给我看这些干啥子?别急啊!大白(●—●),我们向下看

2.@SpringBootApplication剖析

首先我们看点击这个注解进去的当中的三个关键注解

  1. @SpringBootConfiguration
  2. @EnableAutoConfiguration
  3. @ComponentScan ====> 这个注解就是我们为什么Spring会加载@Controller组件关键所在
@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 {

3.@SpringBootConfiguration:

这个注解作用标明此类为配置类,点进去发现就是@Configuration,在加载时加载到Spring IOC

你就把他想成是一个让他拥有配置的角色的作用就行啦===> 给他套个龙袍,当太子

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration    //就是这个注解最关键=====================================
public @interface SpringBootConfiguration {}

4.@EnableAutoConfiguration

**作用:**这个注解可以说是Springboot的灵魂,自动配置,也就是将我们配置文件配置的配置类都加载进来,

它会扫描jar包下面的META-INF/spring.factories文件,将所有符合条件的自动配置类加载到IOC容器中====>是自动配置的核心

为什么?我们点进源码去看看呗,如下的源码,我们会看其中有两个核心的注解 (就是自动配置的关键,这两个注解说明,可以不看,忽略直接看下一个核心注解)

1.@AutoConfigurationPackage

2.@Import(AutoConfigurationImportSelector.class)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

4.1 @AutoConfigurationPackage

点击源码,我们会看到其中的一个: @Import(AutoConfigurationPackages.Registrar.class)

**作用:**借助@Import注解导入符合自动配置类的集合,目的为了加载到IOC容器中

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

AutoConfigurationPackages.Registrar.class的源码,这个可以直接忽略,感兴趣的可以看看

	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {register(registry, new PackageImport(metadata).getPackageName());  //获取包名}@Overridepublic Set<Object> determineImports(AnnotationMetadata metadata) {return Collections.singleton(new PackageImport(metadata));}}

4.2@Import(AutoConfigurationImportSelector.class)

这个类就更重要了,问什么这样说?让我们结合下面的源码一起解读(为了阅读的便利性,只保留所需源码的核心块)

  1. 根据引入的AutoConfigurationImportSelector中的selectImports方法,
  2. 读取所有依赖jar包下面也就是META-INF/spring.factories 下面的文件(怎么借加载此目录下面的呢?===>请看getCandidateConfigurations讲解)
  3. 并且根据加载的条件加载项目所需要的类

通过这三个步骤,也就完成SpringBoot的自动加载 ===> 从而@AutoConfigurationPackage执行结束

public class AutoConfigurationImportSelectorimplements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,BeanFactoryAware, EnvironmentAware, Ordered {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AnnotationAttributes attributes = getAttributes(annotationMetadata);List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);configurations = removeDuplicates(configurations);Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return StringUtils.toStringArray(configurations);}

getCandidateConfigurations:

为了便于确认,我将AutoConfigurationImportSelector类下面此方法单独拎出来

z这个方法会读取所有的’META-INF/spring.factories’的依赖jar包,

获取spring.factories全名称,====.>其实下面的注解也写了 >点击loadFactoryNames方法,> 加载META-INF/spring.factories

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes) {List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());Assert.notEmpty(configurations,"No auto configuration classes found in META-INF/spring.factories. If you "+ "are using a custom packaging, make sure that file is correct.");return configurations;}

5.@ComponentScan

前面的两个注解说完了,我们终于来到此注解,也是解开我心里疑惑的注解了

就特么我解释吗?===> 就是将我们注册@Controller,@Service,等注解自动扫描加到IOC容器中

@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

6.META-INF/spring.factories

这个到底是什么鬼东西???说了半天,我们去看看,其实写这篇博客,按自己也很好奇,哈哈哈

我们走,一起去看看

https://blog.csdn.net/weixin_40017062/article/details/128710518

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/21609.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优质文章集合

开发人员如何停止学习&#xff1a;专家初学者的崛起 How Developers Stop Learning: Rise of the Expert Beginner - DaedTech

使用socket实现UDP版的回显服务器

文章目录 1. Socket简介2. DatagramSocket3. DatagramPacket4. InetSocketAddress5. 实现UDP版的回显服务器 1. Socket简介 Socket&#xff08;Java套接字&#xff09;是Java编程语言提供的一组类和接口&#xff0c;用于实现网络通信。它基于Socket编程接口&#xff0c;提供了…

opencv36-形态学操作-膨胀 cv2.dilate()

膨胀操作是形态学中另外一种基本的操作。膨胀操作和腐蚀操作的作用是相反的&#xff0c;膨胀操作能对图像的边界进行扩张。膨胀操作将与当前对象&#xff08;前景&#xff09;接触到的背景点合并到当前对象内&#xff0c;从而实现将图像的边界点向外扩张。如果图像内两个对象的…

分布式应用:ELFK集群部署

目录 一、理论 1.ELFK集群 2.filebeat 3.部署ELK集群 二、实验 1. ELFK集群部署 三、总结 一、理论 1.ELFK集群 &#xff08;1&#xff09;概念 ELFK集群部署&#xff08;FilebeatELK&#xff09;&#xff0c;ELFK ES logstashfilebeatkibana 。 数据流 架构 2.fi…

零基础C#编写上位机如何入门?

想要学习C#编写上位机&#xff0c;需要具备以下基础知识&#xff1a; C#编程语言基础.NET框架的使用WinForm窗体应用程序开发技术基本的数据结构和算法知识 为了方便理解&#xff0c;我将为您列出一些入门步骤&#xff1a; 学习C#基础语法和.NET框架&#xff0c;掌握基本编程…

【Ajax】笔记-JQuery发送jsonp请求

前端 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>jQuery-jsonp</title><style>#re…

python+opencv实现显示摄像头,截取相关图片,录取相关视频

实时显示摄像头图像 按下空格键&#xff0c;截取图片 按下tab键&#xff0c;开始录制摄像内容&#xff0c;再次按下&#xff0c;结束录制 按下Esc键&#xff0c;关闭窗口 import cv2 import numpy#第几章图片 img_count0InitVideoFalse #第几个视频 video_count0 video_flagFa…

【Linux 网络】 传输层协议之TCP协议 TCP的三次握手和四次挥手

TCP协议 TCP协议段格式谈谈什么是 “可靠” 和 “不可靠”TCP协议段——序号与确认序号TCP协议段——窗口大小TCP协议段 —— 六个标志位确认应答机制&#xff08;ACK&#xff09;超时重传机制连接管理机制TCP 的三次握手四次挥手TCP三次握手四次挥手总结图 滑动窗口流量控制拥…

vue获取近七天、月份、年份的起始日和结束日

vue获取近七天的起始日和结束日 例如&#xff1a;startDate: 2023-07-29 endDate: 2023-08-04 data() {return {startDate: null,endDate: null} }, mounted() {this.calculateDateRange(); }, methods: {calculateDateRange() {var currentDate new Date();var startDate …

将Visio和Excel导出成没有白边的PDF文件

1、VISIO如何无白边导出pdf格式 在使用Latex时&#xff0c;要导入矢量图eps格式。但是VISIO无法输出eps格式&#xff0c;这就需要将其导出为pdf。但是导出pdf时&#xff0c;往往会有大量的白边。VISIO无白边导出pdf格式的方法如下&#xff1a; 1.文件——开发工具——显示sha…

vue中使用Base64加密、解密以及des加密、解密

Base64加密、解密 第一步&#xff1a; npm install js-base64 --save 下载依赖 第二步&#xff1a; 直接引入即可 import { Base64 } from js-base64; 第三步&#xff1a; Base64.encode(xxxx) 其中 .encode() 加密 .decode() 解密 中间不需要使用加密的key等…

OpenLayers入门,OpenLayers解析通过fetch请求的GeoJson格式数据,并叠加要素文字标注,以行政区划边界为例

专栏目录: OpenLayers入门教程汇总目录 前言 本章讲解如何使用OpenLayers通过fetch请求geojson数据,然后通过OpenLayers解析为Feature要素叠加到图层上,并且通过动态设置标注方式显示要素属性为文字标注。 本章还是以行政区划边界为例,这个示例在开发中比较常用,建议收藏…

利用OpenCV实现图像拼接

一、介绍 图像拼接. 二、分步实现 要实现图像拼接&#xff0c;简单来说有以下几步&#xff1a; 对每幅图进行特征点提取对对特征点进行匹配进行图像配准把图像拷贝到另一幅图像的特定位置对重叠边界进行特殊处理 PS&#xff1a;需要使用低版本的opencv&#xff0c;否则无法使…

解密顶象滑动拼图验证码:原理与识别方法详解

在网络世界中&#xff0c;验证码是一种常见的安全措施&#xff0c;用于识别用户是否真实、抵御恶意爬虫攻击。顶象滑动拼图验证码是一种常见而又具有挑战性的验证码形式。本文将详细介绍顶象滑动拼图验证码的原理&#xff0c;并提供一些常见的识别方法&#xff0c;帮助您更好地…

老版MFC工程迁移到VC2019编译EXE太大的问题

有个老版静态链接MFC库的MFC程序需要迁移到VC2019编译&#xff0c;直接用VC2019打开就会自动迁移过去&#xff0c;然后编译一下&#xff0c;生成的EXE大小将近3MB&#xff0c;老版的工程编译出来也就600多KB。 肯定哪里不对劲&#xff01; 好一顿研究之后发现原来默认会把MFC…

【C语言学习】C语言的基础数据类型

一、数据类型 1.整型 short(短整型) int&#xff08;整型 long&#xff08;长整型&#xff09; long long&#xff08;长整型&#xff09;没有特殊需要&#xff0c;就用int 2.浮点型 float&#xff08;单精度型&#xff09; double&#xff08;双精度型&#xff…

Django的生命周期流程图(补充)、路由层urls.py文件、无名分组和有名分组、反向解析(无名反向解析、有名反向解析)、路由分发、伪静态

一、orm的增删改查方法&#xff08;补充&#xff09; 1. 查询resmodels.表名(类名).objects.all()[0]resmodels.表名(类名).objects.filter(usernameusername, passwordpassword).all()res models.表名(类名).objects.first() # 判断&#xff0c;判断数据是否有# res如果查询…

git清除历史纪录

Git 是一种常用的版本控制工具&#xff0c;被广泛用于项目开发中。在项目开发的过程中&#xff0c;我们通常会使用各种 git 命令来进行版本控制和管理&#xff0c;其中包括提交代码&#xff0c;合并分支等操作。然而&#xff0c;在某些情况下&#xff0c;我们可能需要清除 Git …

SAM在医学图像分割的一些研究(Segment Anything Model for Medical Images?(2023))

使用预训练模型通过两种主要模式进行分割&#xff0c;包括自动一切和手动提示(例如&#xff0c;点和框)。SAM在各种自然图像分割任务上取得了令人印象深刻的效果。然而&#xff0c;由于医学图像的形态复杂、解剖结构精细、物体边界不确定和复杂、物体尺度大&#xff0c;使得医学…

iOS——Block one

块类似于匿名函数或闭包&#xff0c;在许多其他编程语言中也存在类似的概念。 可以访问上下文&#xff0c;运行效率高 Block 以下是块的一些基本知识&#xff1a; 块的定义&#xff1a;块是由一对花括号 {} 包围的代码片段&#xff0c;可以包含一段可执行的代码。块的定义使…