SpringBoot自动配置原理

news2025/1/19 2:02:31

1、自动配置原理


1、我们编写的SpringBoot启动类上有一个@SpringBootApplication注解,表示当前类是springboot的启动类(入口类)。

package com.baidou;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication //表示当前类是springboot的启动类
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

点击@SpringBootApplication查看源码:

// 前四个是元注解
@Target(ElementType.TYPE)           // 说明这个注解作用在类或接口上
@Retention(RetentionPolicy.RUNTIME) // 控制注解的生命周期,RUNTIME表示一直存活(源码阶段、字节码文件阶段、运行阶段)
@Documented                         // 是否可以生成文档
@Inherited                          // 是否可以继承

// 核心注解:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
	...
}    

@SpringBootApplication它是一个组合注解:

  • @SpringBootConfiguration:声明当前类是一个springboot的配置类。

  • @EnableAutoConfiguration:支持自动配置

  • @ComponetScan:组件扫描,扫描主类所在的包以及子包里的bean。


2、查看@SpringBootConfiguration注解源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration // 表示这个注解它也是spring的配置类
public @interface SpringBootConfiguration {
   ... 
}

3、@ComponetScan组件扫描,扫描并加载符合条件的Bean到容器中

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

4、查看@EnableAutoConfiguration注解源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited

@AutoConfigurationPackage //指定需要扫描配置的包
@Import(AutoConfigurationImportSelector.class)//导入AutoConfigurationImportSelector这个配置类(加载自动配置的类)
public @interface EnableAutoConfiguration {

4.1、点击@AutoConfigurationPackage注解,发现导入这么一个静态内部类AutoConfigurationPackages.Registrar

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class) //导入Registrar中注册的组件
// @AutoConfigurationPackage注解的主要作用就是将启动类所在包及所有子包下的组件到扫描到spring容器中。
public @interface AutoConfigurationPackage {

	String[] basePackages() default {};

	Class<?>[] basePackageClasses() default {};

}

接着点击Registrar类查看源码:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

    // 给容器中导入某个组件类
    // 根据传入的元注解信息获取所在的包, 将包中组件类封装为数组进行注册
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
    }

    @Override
    public Set<Object> determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new PackageImports(metadata));
    }

}

在这里插入图片描述

使用debug查看它扫描哪个包下的组件:

在这里插入图片描述

这里我们要注意,在定义项目包结构的时候,要定义的非常规范,我们写的代码要放到启动类所在包或子包下,这样才能保证定义的类能够被组件扫描器扫描到。


4.2、@Import(AutoConfigurationImportSelector.class)注解:

导入了一个自动配置类AutoConfigurationImportSelector,表示向spring容器中导入一些组件。

// 实现DeferredImportSelector接口,需要重写一个selectImports方法
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
	ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
	...
   
    // 此方法的返回值都会加载到spring容器中(bean的全限定名数组)
    @Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 判断SpringBoot是否开启自动配置
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}  
       
     // 获取需要自动配置的bean信息
     protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
         // 判断是否开启自动配置
         if (!isEnabled(annotationMetadata)) {
             return EMPTY_ENTRY;
         }
         // 获取@EnableAutoConfiguration注解的属性,也就是exclude和excludeName
         AnnotationAttributes attributes = getAttributes(annotationMetadata);
         // 获取候选的配置
         // 获取到所有需要导入到容器中的配置类
         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文件中配置的过滤器对自动配置类进行过滤                                       
         configurations = getConfigurationClassFilter().filter(configurations);
         fireAutoConfigurationImportEvents(configurations, exclusions);
         return new AutoConfigurationEntry(configurations, exclusions);
     } 
                                                
     protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = 		
            // 扫描所有jar包类路径下 "META-INF/spring.factories文件
            // 在spring-boot-autoconfigure中
            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;
	}  
}

在这里插入图片描述

加载当前项目中所有jar包的META-INF/spring.factories下key为:org.springframework.boot.autoconfigure.EnableAutoConfiguration的value值,他的value值就是这130个自动配置类。(第三方stater整合springboot也要提供spring.factories,stater机制)

在这里插入图片描述

在这里插入图片描述

每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都会加入到容器中;用他们来做自动配置!!!


虽然我们130个自动配置类默认是全部加载,最终它会按照@Conditional条件装配。(生效的配置类就会给容器中装配很多组件)

例如:RedisAutoConfiguration

@Configuration(proxyBeanMethods = false)  //表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件
@ConditionalOnClass(RedisOperations.class) //条件 当项目导入starter-data-redis依赖时才会下限执行
@EnableConfigurationProperties(RedisProperties.class) //让RedisProperties对象读取配置文件中的信息
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) //
public class RedisAutoConfiguration {
    
    //给容器中添加一个组件,这个组件的某些值需要从properties中获取
    @Bean
	@ConditionalOnMissingBean(name = "redisTemplate")//判断容器有没有这个组件,springioc容器中没有则创建
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}
}    

RedisProperties:

@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {

	private int database = 0;

	private String url;

	private String host = "localhost";

	private String username;

	private String password;

	private int port = 6379;

	private boolean ssl;

	private Duration timeout;

	private Duration connectTimeout;

	private String clientName;

	private ClientType clientType;

	private Sentinel sentinel;

	private Cluster cluster;

	private final Jedis jedis = new Jedis();

	private final Lettuce lettuce = new Lettuce();
	...
}    

扫描到这些自动配置类后,要不要创建呢?

这个要结合每个自动配置类上的条件,若条件满足就会创建,一旦创建好自动配置类之后,配置类中所有具有@Bean注解的方法就有可能执行,这些方法返回的就是自动配置的核心对象。

小结:

1、SpringBoot启动会加载大量的自动配置类

2、看看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;

3、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)

4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;

  • xxxxAutoConfigurartion:自动配置类,给容器中添加组件。
  • xxxxProperties:属性类,封装配置文件中相关属性;

【ctrl + n 搜索 *AutoConfiguration 查看默认的写好的所有配置类】

在这里插入图片描述

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

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

相关文章

微信小程序2.9.0基础库canvas2D新API,生成海报保存到手机功能实现

canvasToTempFilePath的官方文档写着在 draw()回调里调用该方法才能保证图片导出成功。文档地址&#xff1a;wx.canvasToTempFilePath(Object object, Object this) | 微信开放文档 我在这里面使用的canva 获取canvas实例&#xff0c;使用的官方的代码。用一个变量canvas保存实…

聊聊 AI 平台存储方案和选型

最近火爆全网的 ChatGPT 再次带来一股 AI 热潮。 过去的五年&#xff0c;AI 快速发展并应用到很多领域中。作为一家存储企业&#xff0c;我们也感受到了 AI 行业的活力&#xff0c;和我们交流团队中&#xff0c;AI 企业越来越多&#xff0c;有自动驾驶、蛋白质结构预测、量化投…

【HTML】【消失的花木兰】花木兰:三兔蹦迪走,安能辨我是兔子?

前言 &#xff08;改编&#xff09;  某日&#xff0c;参军后的花木兰刚回到家乡&#xff0c;却不料遇上抓拿自己的官兵… 因此&#xff0c;花木兰变成兔子躲了起来&#xff0c;你能否找到躲起来的花木兰呢&#xff1f;一起来拭目以待… 一、游戏名称与游戏规则&#xff08…

joinquant量化数据精准吗?

在股票量化投资中&#xff0c;joinquant量化数据起到很大的作用&#xff0c;因为joinquant量化平台的数据能够从众多只股票数据中&#xff0c;能够一一罗列出来&#xff0c;也就是说&#xff0c;joinquant量化数据可以在计算和分析数据模型中&#xff0c;能够帮助投资者找到他们…

【SpringBoot1】创建第一个SpringBoot项目

创建SpringBoot项目可以通过两种方式&#xff1a; 1、通过访问&#xff1a;https://start.spring.io/&#xff0c;SpringBoot的官方网站进行创建SpringBoot项目&#xff1b; 2、通过工具&#xff08;例如&#xff1a;Idea&#xff09;创建SpringBoot项目。本次使用IDEA创建第一…

数据结构进阶 红黑树

作者&#xff1a;小萌新 专栏&#xff1a;数据结构进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍高阶数据结构: 红黑树 红黑树红黑树的概念红黑树的性质红黑树节点的定义红黑树的插入情况一情况二情况三红黑树的验证红黑…

远程监控网络摄像头通用指南

一、引言 随着物联网技术的发展&#xff0c;越来越多的场景需要我们通过技术手段去感知。画面和声音相当于机器的眼睛和耳朵&#xff0c;有了这些实时数据我们可以做很多事情&#xff0c;比如车牌识别、人脸识别、体温识别等等。本文将全方位介绍网络摄像头如何接入软件的实现…

2022.12 青少年机器人技术等级考试理论综合试卷(四级)

2022年12月 青少年机器人技术等级考试理论综合试卷&#xff08;四级&#xff09; 分数&#xff1a; 100 题数&#xff1a; 30 一、 单选题(共 20 题&#xff0c; 共 80 分) 1.以下关于 Arduino C 语言的说法&#xff0c; 正确的是?&#xff08; &#xff09; A.setup() 函数和…

SpringMVC Interceptor拦截器

SpringMVC中的拦截器用于拦截控制器方法的执行&#xff0c;执行在Controller前后&#xff0c;和视图渲染完成后。如下图所示&#xff1a; 一、创建拦截器 继承HandlerInterceptor 接口&#xff0c;并实现其中的方法 public class FirstInterceptor implements HandlerInter…

儿子小伟刚刚再婚,大衣哥就河南新乡商演,这是给孙子攒奶粉钱吗

现如今的社会&#xff0c;因为人们的攀比心理&#xff0c;结一次婚能让人脱一层皮&#xff0c;尤其是农村赚钱难&#xff0c;结婚花钱就更难了。其实不只是普通老百姓&#xff0c;强如农民歌唱家大衣哥这样的人&#xff0c;也架不住儿子一而再&#xff0c;再而三的结婚。 大衣哥…

Qt基础之二十一:QtRO(Qt Remote Object)实现进程间通信

这里将QtRO单独从上一篇Qt基础之二十:进程间通信拎出来,因为它是Qt5.9以后新加入的模块,专门用于进程间通信。其使用步骤有点类似之前介绍过的RPC(Remote Procedure Call)框架:gRPC和thrift,关于这两个框架详见 Qt中调用thrift和Qt中调用gRPC QtRO基于Socket封装,不仅支…

小程序开发——模板与配置

一、WXML 模板语法 1.数据绑定的基本原则 ① 在 data 中定义数据 ② 在 WXML 中使用数据2.在 data 中定义页面的数据 在页面对应的 .js 文件中&#xff0c;把数据定义到 data 对象中即可&#xff1a;3. Mustache 语法的格式 把data中的数据绑定到页面中渲染&#xff0c;使用…

【测试】java+selenium环境搭建

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录一、下载安装谷歌浏览器二、下载谷歌驱动三、常见问题&解决方法1. SessionNotCreatedException2. The version of ChromeDriver only support xxxxxxxxx3. The path to the driver executable the path to普通小…

5-2输入/输出管理-I/O核心子系统

文章目录一.I/O调度二.设备保护三.SPOOLing技术&#xff08;假脱机技术&#xff09;四.设备的分配与回收1.设备分配时应该考虑的因素2.静态分配和动态分配3.设备分配管理中的数据结构&#xff08;1&#xff09;设备控制表DCT&#xff08;Device Control Table&#xff09;&…

MySQL进阶篇之Linux安装MySQL8.0.26

Linux安装MySQL 需要更多安装MySQL的教程&#xff0c;请查阅Linux学习笔记——MySQL数据库管理系统安装部署 1、MySQL下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 2、在FinalShell中输入rz&#xff0c;然后选择下载好的MySQL安装包&#xff0c;进行上…

【数据质量】一起聊聊数据质量

Garbage In, Garbage Out ​ 数据质量关注的是数据的健康&#xff0c;数据健康和人的健康很相似&#xff0c;人的健康会影响人的生活品质&#xff0c;同样数据的健康会影响数据的使用品质。为了保证我们健康&#xff0c;我们需要养成良好的生活习惯&#xff0c;膳食平衡&#x…

Open3D DBSCAN聚类(Python版本)

文章目录 一、简介二、算法步骤三、实现代码四、实现效果参考资料一、简介 DBSCAN算法,全称为“Density-Based Spatial Clustering of Applications with Node”,也就是“基于密度的聚类”。此类算法是假设聚类结构能通过样本分布的紧密程度确定,从样本密度的角度来考察样本…

亿发浅析:财务一体化功能与管理流程

在信息时代的背景下&#xff0c;企业信息化已成为中小企业降低成本、提高效率、提高竞争力的重要手段&#xff0c;也是中小企业实现长期可持续发展的有效途径。 信息化对企业管理的好处是显而易见的&#xff0c;如加快信息流&#xff0c;提高信息资源利用率&#xff0c;促进企业…

STM32使用FSMC驱动LCD

关于FSMC驱动LCD的函数LCD_WR_REG的理解首先你需要理解使用结构体LCD_BASE若有错误&#xff0c;请各位师兄师姐指点原理框图重要的函数理解关于LCD_BASE和函数LCD_WR_REG&#xff08;u16 regval&#xff09;的理解至于0X6C00 0802地址也是一样的。首先要说的是这是我个人的理解…

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 (五)位拆分与运算

数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 &#xff08;五&#xff09;位拆分与运算 &#x1f508;声明&#xff1a; &#x1f603;博主主页&#xff1a;王_嘻嘻的CSDN博客 &#x1f9e8;未经作者允许&#xff0c;禁止转载 &#x1f511;系列专栏&#xff1a;牛客Veri…