SpringBoot核心运行原理解析之-------@EnableAutoConfiguration

这篇具有很好参考价值的文章主要介绍了SpringBoot核心运行原理解析之-------@EnableAutoConfiguration。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

核心运行原理

我们通常在使用Spring Boot时,只需要引入对应的starters,Spring Boot启动时变回自动加载相关依赖,配置相应的初始化参数,以最快捷,简单的形式对第三方软件进行集成,这边是Spring Boot的自动配置功能。下图是Spring Boot实现该运作机制涉及的核心部分:
enableautoconfiguration,SpringBoot源码解析,spring boot,自动配置注解解析,自动配置原理解析,运行原理源码解析
上图简单描述了Spring Boot自动配置功能运作过程中涉及的几个核心功能及其相互之间的关系包括@EnableAutoConfiguration,spring.factories,各组件对应的AutoConfiguration类,@Conditional注解以及各种Starters。
简单概括
Spring Boot通过@EnableAutoConfiguration注解开启自动配置,加载spring.factories中注册的各种AutoConfiguration类,当某个AutoConfiguration类满足其注解@Conditional指定的生效条件(Starters提供的依赖,配置或Spring容器中是否存在某个Bean等)时,实例化该AutoConfiguration类中定义的Bean(组件等),并注入Spring容器,就可以完成依赖框架的自动配置。
核心注解解释

  • @EnableConfiguration:该注解由组合注解@SpringBootApplication引入,完成自动配置开启,扫描各个jar包下的spring.factories文件,并加载文件中注册的AutoConfiguration类等。
  • spring.factories:配置文件,位于jar包下的META-INF目录下,按照指定格式注册了自动配置的AutoConfiguration类。spring.factories也可以包含其他类型待注册的类。改配置文件不仅仅存在于Spring Boot项目中,也可以存在于自定义的自动配置(或starter)项目中。
  • AutoConfiguration:自动配置类,代表了Spring Boot中一类以XXXAutoConfiguration命名的自动配置类。其中定义了三方组件集成Spring所需要的Bean和条件。
  • Conditional:条件注解及其衍生注解,在AutoConfiguration类上使用,当满足该条件注解时才会实例化AutoConfiguration类。
  • Starters:三方组件的依赖及配置,Spring Boot已经预置的组件。Spring Boot默认的Starters项目往往只包含了一个pom依赖的项目。如果是自定的starter,该项目还需要包含spring.factories文件,AutoConfiguration类和其他配置类。

运行原理源码解析之@EnableAutoConfiguration

@EnableAutoConfiguration是开启自动配置的注解,在创建Spring Boot项目看不到该注解,它是由组合注解@SpringBootApplication引入的。先来看下启动类和@SpringBootApplication注解的源码

启动类和@SpringBootApplication注解

/**
 * @author lifly
 * @description
 * @date 2023-04-23 20:46
 * @versoin 1.0.0
 **/
@SpringBootApplication
public class SpringBootApplicationSource {
   
    public static void main(String[] args) {
   
        SpringApplication.run(SpringBootApplicationSource.class,args);
    }
}

相信你们在创建Spring Boot项目时也会有这样一个main方法,启动类的命名规范都是artifactId+Application.通过该启动类就可以启动Spring Boot项目了。这里只能看到一个注解@SpringBootApplication。它是Spring Boot项目的核心注解,包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan注解,它们用于开启自动配置,包扫描,加载配置类。@SpringBootApplication源码如下:

@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 {
   
	//排除制定自动配置类
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {
   };

	//排除指定自动配置类名
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {
   };

	//制定扫描的基础包,激活注解组件的初始化
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {
   };

	//制定扫描的类,用于初始化
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {
   };

	//指定是否代理@Bean方法以强制执行Bean的生命周期行为
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}
  • exclude:根据类(Class)排除指定的自动配置,该成员属性覆盖了@SpringBootApplication中组合的@EnableAutoConfiguration中定义的exclude成员属性。
  • excludeName:根据类名排除指定的自动配置,覆盖了@EnableAutoConfiguration中的excludeName的成员属性。
  • scanBasePackages:指定扫描的基础package,用于激活@Component等注解类的初始化。
  • scanBasePackageClasses:扫描指定的类,用于组件的初始化。
  • proxyBeanMethods:指定是否代理@Bean方法以强制执行bean的生命周期行为。此功能需要通过运行时生成CGLIB子类来实现方法拦截。该子类有一定的限制,比如配置类及其方法不允许声明为final等。proxyBeanMethods的默认值为true,允许配置类中进行inter-bean reference(bean之间的引用)以及对该配置的@Bean方法的外部调用。如果@Bean方法都是自包含的,并且提供了容器使用的普通工程方法的功能,则可设置为false,避免处理CGLIB子类。
    通过以上代码我们发现,Spring Boot中大量使用了@AliasFor注解,该注解用于桥接dao其他注解,该注解的属性中指定了所桥接的注解类。如果点进去查看,会发现@SpringBootApplication定义的属性在其他注解中已经定义过了。之所以使用@AliasFor注解并重新在@SpringBootApplication中定义,更多是为了减少用户使用多注解带来的麻烦。
    @SpringBootApplication注解中组合了@SpringBootConfiguration,@EnableAutoConfiguration和@ComponentScan。因此,在实践过程中也可以使用这3个注解来替代@SpringBootApplication。
    以下是@SpringBootApplication注解组合结构图:
    enableautoconfiguration,SpringBoot源码解析,spring boot,自动配置注解解析,自动配置原理解析,运行原理源码解析

@EnableAutoConfiguration功能解析

在未使用Spring Boot的情况下,Bean的生命周期由Spring管理,然而Spring无法自动配置@Configuration注解的类。而Spring Boot的核心功能之一就是根据约定自动管理该注解标注的类。用来实现该功能的组件之一便是@EnableAutoConfiguration注解。@EnableAutoConfiguration位于spring-boot-autoconfigure包内,当使用@SpringBootApplication注解时,@EnableAutoConfiguration注解会自动生效。@EnableAutoConfiguration的主要功能是启动Spring应用程序上下文时进行自动配置,它会尝试猜测并配置项目可能需要的Bean。自动配置通常是基于项目classPath中引入的和已定义的Bean来实现的。在此过程中,被自动配置的组件来自项目自身和项目依赖的jar包中。
下面来看下@EnableAutoConfiguration注解的源码:

@Target({
   ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({
   AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
   
	//用来覆盖配置开启、关闭自动配置的功能
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	//根据类(class)排除指定的自动配置
    Class<?>[] exclude() default {
   };

	//根据类名排除指定的自动配置
    String[] excludeName() default {
   };
}

@EnableAutoConfiguration注解提供了一个常量和两个成员参数的定义

  • ENABLED_OVERRIDE_PROPERTY :用来覆盖配置开启或关闭的自动配置的功能
  • exclude:根据类(Class)排除指定的自动配置
  • excludeName:根据类名排除指定的自动配置。
    正如上文所说,@EnableAutoConfiguration会猜测你需要使用的Bean,但如果在实战中你并不需要它预配置的Bean,可以通过该注解的exclude或excludeName参数进行有针对性的排除,例如,不需要数据库的自动配置时,可以通过以下两种方法进行排除:
/**
 * @author lifly
 * @description
 * @date 2023-04-23 20:46
 * @versoin 1.0.0
 **/
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class SpringBootApplicationSource {
   
    public static void main(String[] args) {
   
        SpringApplication.run(SpringBootApplicationSource.class,args);
    }
}

/**
 * @author lifly
 * @description
 * @date 2023-04-28 22:16
 * @versoin 1.0.0
 **/
@Configuration
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
public class TestConfiguration {
   
}

注意
被@EnableAutoConfiguration注解的类所在package还具有特定的意义,通常会被作为扫描注解@Entity的根路径。这也是在使用@SpringBootApplication注解时会被注解的类放在顶级package下的原因,如果放在较低级,它所在package的同级或上级中的类无法被扫描到。

AutoConfigurationImportSelector源码分析

@EnableAutoConfiguration的关键功能是通过@Import注解导入的ImportSelector来完成的。从源码得知@Import(AutoConfigurationImportSelector.class)是@EnableAutoConfiguration注解的组成部分,也是自动配置功能的核心实现者。@Import(AutoConfigurationImportSelector.class)又可以分为两个部分:@Import和对应的ImportSelector。

@Import注解

@Import注解位于spring-context项目内,主要提供导入配置类的功能。@Import源码:

@Target({
   ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
   
    Class<?>[] value();
}

@Import的作用和xml配置中"import/"标签的作用一样,我们可以通过@Import引入@Configuration注解的类,也可以导入实现了ImportSelector或ImportBeanDefinitionRegistrar的类,还可以通过@Import导入普通的POJO(将其注册成Spring Bean,导入POJO需要Spring4.2以上版本)。

ImportSelector接口

@Import的许多功能都需要借助接口ImportSelector来实现,ImportSelector决定可引入哪些@Configuration。ImportSelector接口源码如下:

public interface ImportSelector {
   
    String[] selectImports(AnnotationMetadata var1);
}

ImportSelector接口只提供了一个参数为AnnotationMetadata的方法,返回的结果为一个字符串数组。其中参数AnnotationMetadata内包含了被@Import注解的类的注解信息。在selectImports方法内可根据具体实现决定返回哪些配置类的全限定名,将结果以字符串数组的形式返回。
如果实现了接口ImportSelector的类的同时又实现了4个Aware接口,那么Spring保证在调用ImportSelector之前会先调用Aware接口的方法。这4个接口为EnvironmentAware,BeanFactoryAware,BeanClassLoaderAware和ResourceLoaderAware。在AutoConfigurationImportSelector的源代码中就实现了这4个接口

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
   

在上面的源代码中,AutoConfigurationImportSelector并没有直接实现ImportSelector接口,而是实现了它的子接口DeferredImportSelector。DeferredImportSelector接口与ImportSelector的区别是,前者会在所有的@Configuration类加载完成之后再加载返回的配置类,而ImportSelector是在加载完@Configuration类之前加载返回的配置类。
DeferredImportSelector的加载顺序可以通过@Order注解或实现Ordered接口来指定。同时,DeferredImportSelector提供了新的方法getImportGroup()来跨DeferredImportSelector实现自定义Configuration的加载顺序。

AutoConfigutationImportSelector功能概述

下面通过一张图来从整体了解AutoConfigurationImportSelector的核心功能及流程,然后再对照源码看具体的功能实现。
enableautoconfiguration,SpringBoot源码解析,spring boot,自动配置注解解析,自动配置原理解析,运行原理源码解析
当AutoConfigurationImportSelector被@Import注解引入之后,它的selectImports方法会被调用并执行其实现的自动装配逻辑。selectImports方法涵盖了组件自动装配的所有的处理逻辑。AutoConfigurationImportSelector的selectImports方法源码如下:文章来源地址https://www.toymoban.com/news/detail-762082.html

@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
   
		if (!isEnabled(annotationMetadata)) {
   
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
   
		if (!isEnabled(annotationMetadata)) {
   
			return EMPTY_ENTRY;
		}
		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 new AutoConfigurationEntry(configurations, 

到了这里,关于SpringBoot核心运行原理解析之-------@EnableAutoConfiguration的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring】Spring底层核心原理解析

    简单代码: spring.xml内容: AppConfig.class内容: AppConfig.class替代了spring.xml文件,表示spring的配置文件; ApplicationContext在Spring、SpringMVC、SpringBoot中的创建方式: Spring,通过 ClassPathXmlApplicationContext 创建; SpringMVC,通过 XmlWebApplicationContext 创建; SpringBoot,通过 AnnotationConfigAppl

    2024年02月15日
    浏览(23)
  • Spring - Spring底层核心原理解析

    1. Bean的生命周期底层原理 2. 依赖注入底层原理 3. 初始化底层原理 4. 推断构造方法底层原理 5. AOP底层原理 6. Spring事务底层原理 对于这三行代码应该,大部分同学应该都是比较熟悉,这是学习Spring的hello world。可是,这三行代码底层都做了什么,比如: 第一行代码,会构造一

    2024年02月07日
    浏览(36)
  • 【Spring专题】Spring底层核心原理解析

    Spring啊,可以说是我们大部分Java玩家【最熟悉的陌生人】了吧。八个字形容:似懂非懂,会也不会 你说简单应用,我们大家都会,那真要展开说两句的话,那只能来这么两句:这是第一句,接着是第二句,好了我说完了。 但是啊xdm, 据说Spring是一份非常非常非常优秀的源码

    2024年02月13日
    浏览(33)
  • SpringBoot核心原理以及工作流程

    1. SpringBoot 概述 SpringBoot 是Spring的一套快速配置脚手架,快速的将一些常用的第三方依赖整合(原理:通过Maven子父工程的方式),简化xml配置,全部采用注解形式,内嵌web应用容器(如:jetty和Tomcat),最终以java应用程序进行执行 2. SpringBoot的启动类入口 2.1 @SpringBootApplicat

    2024年02月01日
    浏览(40)
  • 走进Spring的世界 —— Spring底层核心原理解析(一)

    这是学习Spring的hello world。可是,这三行代码底层都做了什么,比如: 第一行代码,会构造一个ClassPathXmlApplicationContext对象,ClassPathXmlApplicationContext该如何理解,调用该构造方法除开会实例化得到一个对象,还会做哪些事情? 第二行代码,会调用ClassPathXmlApplicationContext的ge

    2024年02月07日
    浏览(41)
  • Clickhouse分布式表引擎(Distributed)写入核心原理解析

    Clickhouse分布式表引擎(Distributed)写入核心原理解析 Clickhouse分布式表引擎(Distributed)查询核心原理解析 Distributed表引擎是分布式表的代名词,它自身不存储任何数据,而是作为数据分片的透明代理,能够自动路由数据至集群中的各个节点 ,所以Distributed表引擎需要和其他数

    2023年04月27日
    浏览(40)
  • Elasticsearch权威指南:深度解析搜索技术核心概念、原理及实践

    作者:禅与计算机程序设计艺术 2010年,当时仅仅30岁的Elasticsearch创始人黄文坚就率先发布了开源分布式搜索引擎Elasticsearch。从此, Elasticsearch 名扬天下,成为了当前搜索领域的翘楚。随着 Elasticsearch 的快速崛起,越来越多的人开始关注并应用 Elasticsearch 来进行搜索服务。

    2024年02月10日
    浏览(41)
  • 【递归】:原理、应用与案例解析 ,助你深入理解递归核心思想

    递归在计算机科学中,递归是一种解决计算问题的方法,其中解决方案取决于同一类问题的更小子集 例如 递归遍历环形链表 基本情况(Base Case) :基本情况是递归函数中最简单的情况,它们通常是递归终止的条件。在基本情况下,递归函数会返回一个明确的值,而不再进行

    2024年02月21日
    浏览(35)
  • 3、深入解析Redis Cluster集群运维与核心原理

    在今天的大规模分布式系统中,Redis Cluster已经成为了许多企业选择的分布式缓存方案之一。了解Redis Cluster的运维及核心原理对于确保系统的高可用性和性能至关重要。本文将深入探讨Redis Cluster集群的运维细节和核心原理,以帮助读者更好地理解和优化Redis在集群环境下的表

    2024年01月16日
    浏览(32)
  • Spark核心RDD详解(设计与运行原理,分区,创建,转换,行动与持久化)

    在实际应用中,存在许多迭代式算法(比如机器学习、图算法等)和交互式数据挖掘工具,这些应用场景的共同之处是,不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入。但是,目前的MapReduce框架都是把中间结果写入到HDFS中,带来了大量的

    2024年02月04日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包