Spring Boot 源码学习之@EnableAutoConfiguration注解

news2024/11/27 16:42:10

@EnableAutoConfiguration 注解

  • 引言
  • 主要内容
    • 1. @EnableAutoConfiguration 功能解析
      • 1.1 常见的自动配置示例
      • 1.2 源码介绍
    • 2. @Import 注解介绍
    • 3. @AutoConfigurationPackage 注解介绍
  • 总结

引言

Huazie 的上篇博文中,我们详细了解了关于 @SpringBootApplication 注解的一些内容,文章最后提到了 @EnableAutoConfiguration 注解,用来开启 Spring Boot 的自动配置功能,这将是本篇将要重点讲解的内容。

主要内容

1. @EnableAutoConfiguration 功能解析

我们知道,在没有使用 Spring Boot 的情况下,Bean 的生命周期都是由 Spring 来管理的,并且 Spring 是无法自动配置 @Configuration 注解的类。Spring Boot 的核心功能之一就是根据约定自动管理 @Configuration 注解的类 ,其中 @EnableAutoConfiguration 注解就是实现该功能的组件之一。

@EnableAutoConfiguration 注解 位于 spring-boot-autoconfigure 包内,当使用 @SpringBootApplication 注解时,它也就会自动生效。
在这里插入图片描述

结合上面的内容,我们很容易猜到 @EnableAutoConfiguration 注解是用来启动 Spring 应用程序上下文时进行自动配置,它会尝试猜测和配置项目可能需要的 Bean

自动配置通常是根据项目中引入的类和已定义的 Bean 来实现的。在自动配置过程中,会检查项目的classpath(类路径)中引入的类以及项目依赖的 jar 包中的组件。

1.1 常见的自动配置示例

下面我们来看看,常见的自动配置的示例,如下所示:

  • 数据库连接池: 假设项目中引入了 Spring BootJDBC Starter 依赖,它会根据类路径中的相关库(如 HikariCP、Durid、Tomcat JDBC等)自动配置数据库连接池。我们只需在配置文件中提供数据库连接的信息,Spring Boot 将会自动创建并配置连接池。

  • Web应用程序: 当引入了 Spring BootWeb Starter 依赖时,它会自动配置嵌入式的 Web 服务器(如 Tomcat、Jetty、 Undertow等),并为我们提供默认的 Web 应用程序上下文和基本的 Web 配置,例如 Servlet、Filter、Listener 等。

  • Spring MVC: 如果在项目中引入了 Spring MVC 的相关依赖,Spring Boot 会自动配置 基于注解的控制器视图解析器异常处理 等,使得开发 Web 应用变得更加简单。

  • 持久化框架集成: 当引入了特定的持久化框架(如 Hibernate、MyBatis 等)的相关依赖时,Spring Boot 会自动配置相应的 SessionFactory事务管理器 等组件,以帮助你进行数据库操作。

  • 安全框架: 当引入了 Spring Security 的相关依赖时,Spring Boot 会自动配置基本的 安全过滤器链用户认证和授权 等,提供基本的应用程序安全性。

1.2 源码介绍

下面我们来看看 @EnableAutoConfiguration 注解的源码【版本:2.7.9】:

/**
 * 启用Spring应用程序上下文的自动配置,尝试猜测和配置可能需要的Bean。
 * 自动配置类通常基于你的类路径和你已定义的Bean来应用。
 * 例如,如果你在类路径中引入了tomcat-embedded.jar,那么很可能希望有一个
 * TomcatServletWebServerFactory(除非你已经定义了自己的ServletWebServerFactory Bean)。
 * 
 * 当使用@SpringBootApplication注解时,上下文的自动配置会自动启用,因此添加此注解没有额外的效果。
 * 
 * 自动配置试图尽可能智能,并且随着你定义更多自己的配置而退避。
 * 你可以手动使用exclude()方法排除任何你不想应用的配置(如果无法访问它们,
 * 则可以使用excludeName()方法)。你还可以通过spring.autoconfigure.exclude属性来排除它们。
 * 自动配置总是在用户自定义的Bean注册之后应用。
 * 
 * 使用@EnableAutoConfiguration注解标注的类所在的包通常具有特殊意义,并且经常被用作"默认"。
 * 例如,在扫描@Entity类时将使用该包。通常建议将@EnableAutoConfiguration(如果你没有使用
 * @SpringBootApplication)放在根包中,以便可以搜索所有子包和类。
 * 
 * 自动配置类是常规的Spring @Configuration Bean。它们是通过ImportCandidates 和
 * SpringFactoriesLoader 机制(针对这个类进行索引)来定位的。通常,自动配置Bean是
 * @Conditional Bean(通常使用@ConditionalOnClass和@ConditionalOnMissingBean注解)。
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @since 1.0.0
 * @see ConditionalOnBean
 * @see ConditionalOnMissingBean
 * @see ConditionalOnClass
 * @see AutoConfigureAfter
 * @see SpringBootApplication
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	/**
	 * 可以用于覆盖自动配置是否启用的环境属性
	 */
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * 排除特定的自动配置类,以使它们永远不会应用
	 * @return 要排除的类
	 */
	Class<?>[] exclude() default {};

	/**
	 * 排除特定的自动配置类名,以使它们永远不会应用
	 * @return 要排除的类名
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

通过查看源码,我们可以看到 @EnableAutoConfiguration 注解提供了一个常量 和 两个成员变量:

  • ENABLED_OVERRIDE_PROPERTY : 用于覆盖自动配置是否启用的环境属性
  • exclude :排除特定的自动配置类
  • excludeName :排除特定的自动配置类名

正如前面所说, @EnableAutoConfiguration 会尝试猜测并配置你可能需要的 Bean,但实际情况如果是我们不需要这些预配置的 Bean,那么也可以通过它的两个成员变量 excludeexcludeName 来排除指定的自动配置。

// 通过 @SpringBootApplication 排除 DataSourceAutoConfiguration
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DemoApplication {

}

或者:

// 通过 @EnableAutoConfiguration 排除 DataSourceAutoConfiguration
@Configuration
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
public class DemoConfiguration {
}

注意:
Spring Boot 在进行实体类扫描时,会从 @EnableAutoConfiguration 注解标注的类所在的包开始扫描。这也是在使用 @SpringBootApplication 注解时需要将被注解的类放在顶级 package 下的原因,如果放在较低层级,它所在 package 的同级或上级中的类就无法被扫描到,从而无法正常使用相关注解(如 @Entity)。

从我们上篇博文中新建的 Spring Boot 项目可知,@SpringBootApplication 注解通常用于标记 Spring Boot 应用程序的入口类。它会自动启用 Spring Boot 的自动配置和组件扫描等功能。但是,如果你希望将自动配置应用于其他类,而不是入口类本身,那么你可以将 @SpringBootApplication 注解添加到这些类上。同样地,@EnableAutoConfiguration 注解也可以用于其他类,而不仅限于入口类。这个注解用于启用Spring 的自动配置功能,并根据类路径和已定义的Bean来自动配置应用程序上下文。

因此,在 Spring Boot 应用程序中,入口类只是一个用来引导应用程序的类,而真正的自动配置和功能开启是通过 @SpringBootApplication@EnableAutoConfiguration 注解所用的其他类完成的。

2. @Import 注解介绍

从上面 @EnableAutoConfiguration 注解的源码可知,@Import(AutoConfigurationImportSelector.class) 也是@EnableAutoConfiguration 注解的组成部分,这也是自动配置功能的核心实现者。

下面我们重点讲解一下 @Import 注解,至于它对应的 ImportSelector ,我们将在后续的博文中详细介绍。

@Import 注解位于 spring-context 项目内,主要提供导入配置类的功能。在后续的学习源码的过程中,我们会发现有大量的 EnableXXX 类使用了@Import 注解。

下面我们来看一下 @Import 的源码【版本 spring-context-5.3.25】:

/**
 * 指示导入一个或多个组件类,通常是@Configuration类。
 * 
 * 提供与Spring XML中的<import/>元素相当的功能。允许导入@Configuration类、
 * ImportSelector 和 ImportBeanDefinitionRegistrar 实现,以及普通的组件类
 * (从4.2开始;类似于AnnotationConfigApplicationContext.register)。
 * 
 * 在导入的 @Configuration 类中声明的@Bean定义应该通过@Autowired注入来访问。
 * 可以将bean本身进行自动装配,也可以将声明bean的配置类实例进行自动装配。
 * 后一种方法允许在@Configuration类方法之间进行显式且友好的导航(适用于IDE)。
 * 
 * 可以在类级别或作为元注解进行声明。
 * 
 * 如果需要导入XML或其他非 @Configuration 的bean定义资源,请使用 @ImportResource 注解来实现。
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.0
 * @see Configuration
 * @see ImportSelector
 * @see ImportBeanDefinitionRegistrar
 * @see ImportResource
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

	/**
	 * @Configuration、ImportSelector、ImportBeanDefinitionRegistrar 或常规组件类可以用来进行导入。
	 */
	Class<?>[] value();

}

上面的源码注释中,已经将 @Import 注解上的英文注释翻译成了中文注释,大家可以阅读了解下,这里就不再展开介绍了。

3. @AutoConfigurationPackage 注解介绍

细心的朋友可能发现了,在 @EnableAutoConfiguration 注解的源码中,还有一个 @AutoConfigurationPackage 注解。

那么 @AutoConfigurationPackage 注解有啥作用呢?

在解答之前,我们先来看看 @AutoConfigurationPackage 注解的源码【版本 2.7.9 】:

/**
 * 将包注册到 AutoConfigurationPackages 中。
 * 当没有指定基础包或基础包类时,将会注册带有注解类的包。
 *
 * @author Phillip Webb
 * @since 1.3.0
 * @see AutoConfigurationPackages
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

	/**
	 * 应该注册到 AutoConfigurationPackages 的基础包。
	 * 使用 basePackageClasses 作为基于类型安全的替代方法,而不是基于字符串的包名。
	 * 
	 * @since 2.3.0
	 */
	String[] basePackages() default {};

	/**
	 * @AutoConfigurationPackage 提供了一种类型安全的替代方案,用于指定要注册到 AutoConfigurationPackages 的包。
	 * 考虑在每个包中创建一个特殊的无操作标记类或接口,除了被此属性引用外,不具备任何其他功能。
	 * 
	 * @since 2.3.0
	 */
	Class<?>[] basePackageClasses() default {};

}

通过上述阅读源码,我们可以看到 @AutoConfigurationPackage 上有如下这段代码:

@Import(AutoConfigurationPackages.Registrar.class)

通过上面的 @Import 注解介绍,我们可以知道,这段代码的作用其实就是通过导入AutoConfigurationPackages.Registrar 类【其中 ImportBeanDefinitionRegistrar 用于存储导入配置的基础包信息】,将基础包及其子包注册到 AutoConfigurationPackages 中,以便实现自动配置的功能。

通常情况下,Spring Boot 应用程序会将主配置类(例如使用 @SpringBootApplication 注解的类)置于根包中。这样做的话,根包会作为默认的扫描路径,用于自动发现和注册 Spring 组件(如@Controller、@Service、@Repository 等)。

当使用 @AutoConfigurationPackage 注解时,它会将指定类所在的包及其子包中的组件自动注册到Spring应用程序上下文中,即自动装配这些组件,从而简化了组件的配置和使用。

总结

本篇笔者介绍了 @EnableAutoConfiguration 注解的相关功能,当然其中真正实现自动配置功能的核心实现者 AutoConfigurationImportSelector 还没有详细说明,那下一篇博文我们将重点对 AutoConfigurationImportSelector 的源码进行学习,敬请期待!!!

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

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

相关文章

【论文阅读 03】机器学习算法在颈动脉斑块影像学分类中的研究进展

读完之后就是&#xff0c;总结 机器学习&#xff08;SVM、小波&#xff09;和深度学习&#xff08;CNN&#xff09;在 颈动脉斑块影像学中的 分类效果。只讨论了超声、磁共振两种成像 Chin J Clin Neurosci 临床神经科学杂志 复旦大学 颈动脉斑块( carotid plaques) 是一种…

JavaScript基础篇(31-40题)

此文章&#xff0c;来源于印客学院的资料【第一部分&#xff1a;基础篇(105题)】&#xff0c;也有一些从网上查找的补充。 这里只是分享&#xff0c;便于学习。 诸君可以根据自己实际情况&#xff0c;自行衡量&#xff0c;看看哪里需要加强。 概述如下&#xff1a; javascri…

使用Docker在局域网安装GitLab

使用 Docker 安装 GitLab 1. 安装GitLab 最近想在本地创建一个GitLab仓库&#xff0c;简单记录一下&#xff1a; 简单设置一个GitLab信息的存储目录 export GITLAB_HOME/etc/docker/gitlab/ && mkdir &GITLAB_HOMEdocker中启动 sudo docker run --detach \# 以…

C++:类和对象(上)---初步认识类和this指针

文章目录 面向过程和面向对象类的引入类的定义类定义的方式 类的访问限定符类的实例化类对象模型类对象的大小 this指针 面向过程和面向对象 C语言是一门面向过程的语言关注的是过程&#xff0c;确认一个问题求解的步骤&#xff0c;再一步一步对它进行解决 C是一门基于面向对…

【学会动态规划】最小路径和(9)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…

Kotlin 协程基础入门:Channel(通道)

简介 Kotlin 中的 Channel&#xff08;通道&#xff09;是一种协程间通信的机制&#xff0c;用于在协程之间传递数据。它提供了一种有序、线程安全的方式&#xff0c;让生产者和消费者之间进行异步数据传输。 Channel 这个管道的其中一端&#xff0c;是发送方&#xff1b;管道…

OpenCV实现照片换底色处理

目录 1.导言 2.引言 3.代码分析 4.优化改进 5.总结 1.导言 在图像处理领域&#xff0c;OpenCV是一款强大而广泛应用的开源库&#xff0c;能够提供丰富的图像处理和计算机视觉功能。本篇博客将介绍如何利用Qt 编辑器调用OpenCV库对照片进行换底色处理&#xff0c;实现更加…

Promise 讲解,js知识,es6

文章目录 一、Promise的三种状态1. 初始态pending2. 成功态fulfilled&#xff0c;调用resolve方法3. 失败态rejected&#xff0c;调用reject方法 二、Promise的方法then方法catch方法 三、async和awaitasync 函数await 表达式 四、代码举例帮助理解1、Promise的值通过then方法获…

【idea】编译热部署

项目场景&#xff1a; 实际工作中&#xff0c;用到了idea&#xff0c;发现idea不编译代码&#xff0c;热部署什么的都不行 问题描述 在实际的工作中idea遇到了各种问题&#xff0c;之前一直用的2022版的&#xff0c;公司用的jboss起的项目&#xff0c;启动过程极其痛苦&#…

电子档案管理系统

电子文档 登陆成功后点击左上角“”选择“档案管理”跳转到“档案管理首页”如下图: 该界面列出用户被授权查看的可视化数据图形,柱图、饼图、线图、雷达图等,并结合数据仓库里的动态数据进行数据展现。 图形所展示的数据可根据企业需求定制,点击图形即可查看关联内容,方…

C++类与对象(上部曲)

目录 面向过程和面向对象初步认识 类的引入 类的定义 类的两种定义方式&#xff1a; 1. 声明和定义全部放在类体中 2. 类声明放在.h文件中&#xff0c;成员函数定义放在.cpp文件中 类的访问限定符及封装 1 访问限定符 2 封装 类的实例化 类对象的存储方式 this指针 …

IDEA快速创建SpringBoot

文件具有错误的版本 61.0, 应为 52.0报错可以看看是不是Springboot的版本比较高 和jdk版本不匹配 package com.qf.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframewor…

黑马 pink h5+css3+移动端前端

网页概念 网页是网站的一页,网页有很多元素组成,包括视频图片文字视频链接等等,以.htm和.html后缀结尾,俗称html文件 HTML 超文本标记语言,描述网页语言,不是编程语言,是标记语言,有标签组成 超文本指的是不光文本,还有图片视频等等标签 常用浏览器 firefox google safari…

从Vue2到Vue3【四】——Composition API(第四章)

系列文章目录 内容链接从Vue2到Vue3【零】Vue3简介从Vue2到Vue3【一】Composition API&#xff08;第一章&#xff09;从Vue2到Vue3【二】Composition API&#xff08;第二章&#xff09;从Vue2到Vue3【三】Composition API&#xff08;第三章&#xff09;从Vue2到Vue3【四】C…

os.environ[“CUDA_VISIBLE_DEVICES“]学习总结

今天发现一个很有意思的东西 import torch import os # Specify the GPU device os.environ["CUDA_VISIBLE_DEVICES"] "1" print(torch.cuda.is_available())但是如果修改下面的设置后&#xff0c;结果就变成了 import torch import os # Specify the…

【100天精通python】Day7:数据结构_列表 List的创建、删除、访问、遍历、统计、排序、推导等使用

目录 1 列表的创建 2 列表的删除 3 访问列表元素 4 遍历列表 5 添加修改删除列表元素 6 对列表进行统计和计算 7 对列表进行排序 8 列表推导式 9 多维列表 在Python中&#xff0c;列表是一种有序的可变数据类型&#xff0c;用于存储一组元素。 列表使用方括号“[] ”来…

汇编习题1-100和

.text .globl _start_start:mov r0,#0MOV r1,#0stop:cmp r1,#0x64addcc r1,r1,#0x1addcc r0,r0,r1b stop .end运行结果&#xff1a; 寄存器R0就为16进制的结果

K8S初级入门系列之四-Namespace/ConfigMap/Secret

一、前言 本章节我们继续学习Namespace、ConfigMap、Secret基础概念&#xff0c;了解他们基本用法和操作。NameSpace为命名空间&#xff0c;在同一集群中试下资源隔离。ConfigMap通过key-value的方式实现明文配置数据的保存&#xff0c;Secret与ConfigMap类似&#xff0c;不过是…

Windows下使用rocketMq

1、下载&#xff08;下载zip后解压即可&#xff09; 下载地址&#xff1a;下载 | RocketMQ 2、配置环境变量&#xff08;注意&#xff1a;该目录的下一级是bin&#xff09; 3、启动 在bin目录下使用cmd 分别输入 3.1 启动name server (下图是启动成功的显示&#xff0c;窗口…

CPU密集型和IO密集型任务的权衡:如何找到最佳平衡点

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、CPU密集型与IO密集型3.1、CPU密集型3.2、I/O密…