【Spring Boot 源码学习】@EnableAutoConfiguration 注解

简介: 本篇我们一起从源码学习 @EnableAutoConfiguration 注解

微信图片_20231031101034.png

引言

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

主要内容

1. @EnableAutoConfiguration 功能解析

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

@EnableAutoConfiguration 注解 位于 spring-boot-autoconfigure 包内,当使用 @SpringBootApplication 注解时,它也就会自动生效。
微信图片_20231031102317.png

结合上面的内容,我们很容易猜到 @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 的源码进行学习,敬请期待!!!

目录
相关文章
|
11天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
30 0
|
7天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
23 2
|
18天前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
41 4
SpringBoot必须掌握的常用注解!
|
13天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
39 9
|
14天前
|
存储 安全 Java
springboot当中ConfigurationProperties注解作用跟数据库存入有啥区别
`@ConfigurationProperties`注解和数据库存储配置信息各有优劣,适用于不同的应用场景。`@ConfigurationProperties`提供了类型安全和模块化的配置管理方式,适合静态和简单配置。而数据库存储配置信息提供了动态更新和集中管理的能力,适合需要频繁变化和集中管理的配置需求。在实际项目中,可以根据具体需求选择合适的配置管理方式,或者结合使用这两种方式,实现灵活高效的配置管理。
12 0
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
152 1
|
21天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
96 62
|
19天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
37 2
|
22天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
221 3
基于Java+Springboot+Vue开发的大学竞赛报名管理系统