【Java】springboot的自动配置

        如果你用过 Spring Boot,一定对 “引入依赖就能用” 的体验印象深刻 —— 加个spring-boot-starter-web就有了 Web 环境,这个是 SpringBoot 的自动装配(Auto-Configuration)机制。

自动装配的核心注解

        自动装配的逻辑看似复杂,其实核心流程只有 3 步:触发自动装配 → 加载配置类 → 条件筛选组件。

1. 第一步:触发自动装配 ——@SpringBootApplication 注解。

        Spring Boot 应用的启动类上,都会有一个@SpringBootApplication注解,比如:

@SpringBootApplication
public class SpringBootDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringBootDemoApplication.class, args);}
}

        这个注解是 “组合注解”,它的核心功能来自其中的 **@EnableAutoConfiguration**注解,触发了自动装配的整个流程。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 1. 开启自动配置(核心)
@EnableAutoConfiguration
// 2. 扫描当前包及子包的Bean(如@Controller、@Service)
@ComponentScan(excludeFilters = { ... })
// 3. 允许在启动类上定义Bean(如@Bean)
@SpringBootConfiguration
public @interface SpringBootApplication {// 省略属性...
}

其中,@EnableAutoConfiguration 是自动装配的 “总开关”,它又依赖两个关键机制:​

  • @Import(AutoConfigurationImportSelector.class):导入一个 “配置选择器”,负责加载自动配置类;​
  • SpringFactoriesLoader:Spring 的一个工具类,负责从指定文件中加载配置类列表。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}

2. 第二步:加载配置类 —— 从 META-INF/spring.factories 中加载配置

        AutoConfigurationImportSelector的核心作用,是通过SpringFactoriesLoader,加载classpath 下所有 META-INF/spring.factories 文件中配置的 “自动配置类”。

        (1)什么是 spring.factories?​

        这是一个键值对格式的配置文件,Spring Boot 的核心 starter(如mybatis-pus)中就自带这个文件,路径在:mybatis-plus-boot-starter\3.5.2\mybatis-plus-boot-starter-3.5.2.jar!\META-INF\spring.factories:

(2)AutoConfigurationImportSelector 的工作流程​

当应用启动时,AutoConfigurationImportSelector会执行以下操作:​

        1、调用selectImports()方法,触发配置类加载;​

// 方法作用:选择需要导入的自动配置类,返回类的全限定名数组
public String[] selectImports(AnnotationMetadata annotationMetadata) {// 第一步:判断自动装配是否启用// isEnabled方法会检查@EnableAutoConfiguration注解的启用状态if (!this.isEnabled(annotationMetadata)) {// 如果未启用,返回空数组(NO_IMPORTS是Spring定义的空数组常量)return NO_IMPORTS;} else {// 第二步:获取自动配置条目(核心逻辑)// 该方法会加载、筛选并确定最终需要生效的配置类AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}
}

        2、调用getAutoConfigurationEntry()方法

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return EMPTY_ENTRY;} // 获取 @EnableAutoConfiguration 注解的属性(如 exclude、excludeName 等)AnnotationAttributes attributes = this.getAttributes(annotationMetadata);// 加载所有候选自动配置类(数据源:META-INF/spring.factories)// 调用我们之前解析过的 getCandidateConfigurations 方法,获取原始候选配置类列表List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);configurations = this.removeDuplicates(configurations);
spring.autoconfigure.excludeSet<String> exclusions = this.getExclusions(annotationMetadata, attributes);this.checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);
@ConditionalOnClass、@ConditionalOnBean)configurations = this.getConfigurationClassFilter().filter(configurations);this.fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
}

        3、调用getCandidateConfigurations()方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {// 第一个参数:指定加载的工厂类类型(这里是EnableAutoConfiguration.class)// 第二个参数:类加载器(用于读取类路径下的资源)List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(),  // 返回EnableAutoConfiguration.classthis.getBeanClassLoader()                    // 获取当前的类加载器);// 如果为空,抛出异常提示(通常是因为找不到META-INF/spring.factories文件)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;
}protected Class<?> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;
}

3. 第三步:条件筛选@Conditiona

加载到自动配置类后,Spring Boot 并不是无条件地启用所有配置,而是通过条件注解进行筛选。

常用的条件注解有:

  • @ConditionalOnClass:当类路径中存在指定类时生效
  • @ConditionalOnMissingClass:当类路径中不存在指定类时生效
  • @ConditionalOnBean:当容器中存在指定 Bean 时生效
  • @ConditionalOnMissingBean:当容器中不存在指定 Bean 时生效
  • @ConditionalOnProperty:当指定的属性有特定值时生效
  • @ConditionalOnWebApplication:当应用是 Web 应用时生效

例如:

@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {// 配置内容...
}

自定义自动配置

1、定义我们需要装配的类

结构:

DataSourceAutoconfiguration类

@Configuration
@EnableConfigurationProperties(DataSourcePropertie.class) // 批量注入
public class DataSourceAutoconfiguration {@Bean()public DataSource dataSource(DataSourcePropertie dataSourcePropertie) {try {ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();comboPooledDataSource.setJdbcUrl(dataSourcePropertie.getJdbcUrl());comboPooledDataSource.setDriverClass(dataSourcePropertie.getDriverName());comboPooledDataSource.setUser(dataSourcePropertie.getUsernames());comboPooledDataSource.setPassword(dataSourcePropertie.getPasswords());return comboPooledDataSource;} catch (PropertyVetoException e) {throw new RuntimeException(e);}}
}

DataSourcePropertie

@ConfigurationProperties(prefix = "datasouce")// 注入前缀为datasouce
public class DataSourcePropertie {private String jdbcUrl = "jdbc:mysql://localhost:3306/summer_practice";private String driverName = "com.mysql.cj.jdbc.Driver";private String usernames = "root1";private String passwords = "1234561";public String getJdbcUrl() {return jdbcUrl;}public void setJdbcUrl(String jdbcUrl) {this.jdbcUrl = jdbcUrl;}public String getDriverName() {return driverName;}public void setDriverName(String driverName) {this.driverName = driverName;}public String getUsernames() {return usernames;}public void setUsernames(String usernames) {this.usernames = usernames;}public String getPasswords() {return passwords;}public void setPasswords(String passwords) {this.passwords = passwords;}
}

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.ape.redisspringbootautoconfigure.DataSourceAutoconfiguration

pom.xml

    </properties><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><!--c3p0--><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

2、配置咋们的启动类(我们只需要在pom.xml中导入需要装配类的坐标)

结构:

pom.xml

        <dependency><groupId>com.ape</groupId><artifactId>redis-spring-boot-autoconfigure</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>

3、在启动类中就可以拿到我们自定义的配置类

@SpringBootApplication
public class SpringbootStarter04Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(SpringbootStarter04Application.class, args);DataSource bean = context.getBean(DataSource.class);System.out.println(bean);}}

4、配置文件(可选)

        由于我们在需要装配的类中添@EnableConfigurationProperties(DataSourcePropertie.class)该注解,所以我们可以在启动类中配置yml文件来替换需要装配的类的数据,从而实现动态的改变其中的数据。

yml

datasouce:usernames: rootpasswords: 123456

总结

        Spring Boot 的自动装配机制通过@EnableAutoConfiguration注解、SpringFactoriesLoader加载机制以及条件注解,实现了基于约定的自动配置,极大地简化了 Spring 应用的开发。允许我们通过自定义配置来覆盖默认行为,可以实现个性化定制。

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

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

相关文章

高通机型QPST平台线刷教程 线刷全分区 只通过引导文件提取单分区 写入单分区

高通芯片机型刷机平台很多&#xff0c;除过一些厂家专用的平台外。qpst是高通芯片类通用刷写平台。其操作简单 可以刷写完整固件。也可以通过单个引导文件来读取 提取整个分区。而且包含读写基带qcn等等的一些功能。 qpst工具下载 QPST 的不同版本可在多个开源平台或技术论坛中…

ES_预处理

1. 预处理的核心概念&#xff1a;什么是 Ingest Pipeline&#xff1f; 想象一下数据进入 Elasticsearch 的旅程。原始数据&#xff08;Raw Data&#xff09;往往并不完美&#xff1a;格式可能混乱&#xff0c;字段可能缺失&#xff0c;或者需要被丰富和转换后才能发挥最大的价值…

我从零开始学习C语言(15)- 基本类型 PART2

开始学习第七章其余部分。7.3.4 转义序列正如在前面示例中见到的那样&#xff0c;字符常量通常是用单引号括起来的单个字符。然而&#xff0c;一些特殊符号&#xff08;比如换行符&#xff09;是无法采用上述方式书写的&#xff0c;因为它们不可见&#xff08;非打印字符&#…

K8S的部署与常用管理

一、k8s的部署 1.1.集群环境初始化 1.1.1.所有主机禁用swap [rootk8s- ~]# systemctl mask dev-nvme0n1p3.swap [rootk8s- ~]# swapoff -a [rootk8s- ~]# systemctl status dev-nvme0n1p3.swap [rootk8s- ~]# vim /etc/fstab 内容&#xff1a; 注释swap 1.1.2.安装k8s部署工…

2025年机械工程与自动化技术国际会议(ICMEAT 2025)

2025年机械工程与自动化技术国际会议&#xff08;ICMEAT 2025&#xff09; 2025 International Conference on Mechanical Engineering and Automation Technology一、大会信息会议简称&#xff1a;ICMEAT 2025 大会地点&#xff1a;中国杭州 审稿通知&#xff1a;投稿后2-3日内…

高数 不定积分(4-3):分部积分法

文章目录写在前面分部积分法&#x1f615; 一个小问题✨ 分部积分法是怎么来的&#xff1f;&#x1f330; 几个小例子⭐ 最终总结&#xff01;后话写在前面 文章传送门&#xff1a;高数 不定积分&#xff08;4-2&#xff09;&#xff1a;换元积分法 今天再更一篇:) 上篇文章&…

Chrome/360 浏览器 WebUI 资源底层机制解析:共享资源与专属资源的奥秘

在 Chromium 和 360 浏览器源码中&#xff0c;我们会发现 WebUI 页面不仅有 C 逻辑处理&#xff08;如 WebUIMessageHandler&#xff09;&#xff0c;还伴随着大量 HTML、CSS 和 JS 文件。尤其是 src/ui/webui/resources 和 src/chrome/browser/360/webui 这两个目录&#xff0…

基于springboot的高校后勤保修服务系统/基于android的高校后勤保修服务系统app

基于springboot的高校后勤保修服务系统/基于android的高校后勤保修服务系统app

Qt QML 用Q_PROPERTY快捷访问c++属性

在之前我写过如何调用函数&#xff0c;当时的属性都是手搓的&#xff0c;也就是自己写成员变量、变化信号和读写函数&#xff0c;但其实有一个很便捷的方法&#xff0c;即使用Q_PROPERTY&#xff0c;下面给出标准结构&#xff1a;Q_PROPERTY(数据类型 变量名 READ 变量名 WRITE…

ubuntu中网卡的 IP 及网关配置设置为永久生效

要将 Ubuntu 中 ens33 和 ens36 网卡的 IP 及网关配置设置为永久生效&#xff08;重启后不丢失&#xff09;&#xff0c;需通过 netplan 配置并禁用 cloud-init 对网络的干扰&#xff08;避免重启后配置被覆盖&#xff09;&#xff0c;具体步骤如下&#xff1a;一、最终的永久生…

不再让Windows更新!Edge游戏助手卸载及关闭自动更新

文章目录Windows系统更新问题方法一&#xff1a;通过注册表手动设置1. 打开注册表编辑器2. 定位到目标路径3. 创建新的DWORD值4. 修改数值方法二&#xff1a;命令行设置1. 打开命令提示符2. 输入命令验证设置是否生效恢复更新Edge关闭游戏助手Edge关闭后台运行Edge关闭自动更新…

css3之flex布局

flex布局要牢记的两个知识点&#xff1a; 开启了flex布局的元素叫flex containerflex container里面的直接子元素叫flex items 这两点要记牢&#xff0c;设置属性的时候才不会搞混这个是flex布局的整体图 一、flex container上的属性 1.flex-direction 修改主轴方向的属性&…

vscode 搭建C/C++开发环境搭建(linux)

1.编译器/调试器安装首先&#xff0c;需要安装编译器&#xff08;GCC/G&#xff09;和调试器&#xff08;GDB&#xff09;,用于编译和调试代码。1.打开终端(Ctrl Alt T)2.更新软件包获取新版本信息sudo apt update3.安装build-essential包,它包含gcc,g等必要库sudo apt install…

vue-pure-admin页面引入和功能添加流程解析

vue-pure-admin (opens new window)是一款开源完全免费且开箱即用的中后台管理系统模版。完全采用 ECMAScript 模块&#xff08;ESM&#xff09;规范来编写和组织代码&#xff0c;使用了最新的 Vue3、Vite、Element-Plus、TypeScript、Pinia、Tailwindcss 等主流技术开发 以下是…

vlc-android: 编译自己的libvlc

概述 VLC 媒体播放器作为一款由志愿者开发团队精心维护的自由、开源且跨平台的多媒体播放器&#xff0c;能轻松驾驭绝大多数多媒体文件&#xff0c;无论是本地磁盘中的视频、音频&#xff0c;还是来自网络的流媒体协议. VLC for Android 支持网络串流&#xff0c;无论是基于 H…

并联谐振与串联谐振

在LC电路中&#xff0c;感抗和容抗相等时对应的频率值称为谐振频率&#xff0c;在接收广播电视信号或无线通信信号时&#xff0c;使接收电路的频率与所选择的发射的信号频率相同就叫做调谐。并联谐振LC并联谐振电路是指将电感器和电容器并联形成&#xff0c;如图所示。在并联谐…

打印机怎么连接电脑?打印机驱动?【图文详解】USB连接打印机?wifi连接打印机?

一、问题背景 在日常办公与生活里&#xff0c;把电脑和打印机连接起来&#xff0c;是实现文档、照片等打印的基础操作。但很多人初次尝试时&#xff0c;会因不熟悉流程而感到无从下手。 无论是办公场景下急需打印重要文件&#xff0c;还是日常生活中想要打印照片留念&#xff0…

CVPR 2025 | 医学影像加速进化:深度学习×多模态,精准诊断再升级

关注gongzhonghao【CVPR顶会精选】今天聊一个医学图像领域的前沿探索&#xff1a;结合空间感知卷积、扩散模型与视觉语言模型&#xff0c;从图像配准到合成分割&#xff0c;再到跨模态理解&#xff0c;打造了一个更加智能、鲁棒且可泛化的医学影像工具链。无论是SACB-Net带来的…

[每周一更]-(第157期):深入理解Go语言的垃圾回收机制:调优与监控

Go语言以其简洁的语法和强大的并发能力而闻名&#xff0c;而它的垃圾回收&#xff08;GC&#xff09;机制则是支撑其高性能的关键组件之一。本文将深入探讨Go语言的垃圾回收原理&#xff0c;并介绍如何对其进行调优与监控&#xff0c;以提升应用程序的性能。 Go语言垃圾回收机制…

Java 学习笔记(基础篇9)

1. 综合练习题目 1 &#xff1a;金额转换为中文大写格式请编写一个 Java 程序&#xff0c;实现将数字金额转换为中文大写格式&#xff08;带单位&#xff09;的功能&#xff0c;具体要求如下&#xff1a;(1) 程序接收用户输入的一个整数金额&#xff08;范围&#xff1a;0-9999…