简单详细的SpringBoot自动配置原理解析

简单详细的SpringBoot自动配置原理解析SpringBoot启动会根据条件加载配置

大家好,又见面了,我是你们的朋友全栈君。

前言

上一篇文章我们介绍了SpringFactoriesLoader,之所以介绍SpringFactoriesLoader是因为我们这篇文章要介绍的SpringBoot的自动配置会用到SpringFactoriesLoader的知识。闲话少叙,让我们直入主题。

环境

spring-boot 1.5.8.RELEASE

从启动类开始

@SpringBootApplication
public class HelloworldDemoApplication { 
   

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

如上,就是我们SpringBoot应用的启动类。让我们把眼光聚焦到@SpringBootApplication注解上面。这个注解是SpringBoot项目的主配置类。

@SpringBootApplication

//省略部分注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { 
   
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication { 
   
}

根据前几篇的介绍,我们可以知道@SpringBootApplication注解是一个组合注解。
@SpringBootConfiguration注解 表示这是SpringBoot的配置类,
@ComponentScan 开启组件扫描
@EnableAutoConfiguration这个注解的作用就是让SpringBoot开启自动配置。自动配置的奥秘全都在这里:

@EnableAutoConfiguration

//省略部分注解
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration { 
   

}

如上我们可以看到EnableAutoConfiguration注解上有两个注解

  1. @AutoConfigurationPackage 注解,
    从字面意思上来看就是自动配置包。点进去可以看到就是⼀个 @Import 注解: @Import(AutoConfigurationPackages.Registrar.class) ,导⼊了⼀个
    Registrar 的组件,这个注解的作用就是将主配置类(@SpringBootConfiguration标注的类)所在的包及其下面所有子包里面所有的组件扫描到IOC容器中。所以说,默认情况下主配置类所在包及其子包以外的组件,Spring IOC容器是扫描不到的。
  2. @Import(AutoConfigurationImportSelector.class)
    通过@Import导入了AutoConfigurationImportSelector类,而这个类的selectImports方法会通过SpringFactoriesLoader得到大量的配置类。而每个配置类则根据条件化配置类做出决策,以实现自动配置的功能。下面就让我们来看看selectImports方法。

AutoConfigurationImportSelector的selectImports方法

	public String[] selectImports(AnnotationMetadata annotationMetadata) { 
   
		//省略部分代码
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		return StringUtils.toStringArray(configurations);
	}
	
		protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) { 
   
			
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		return configurations;
	}
	
	protected Class<?> getSpringFactoriesLoaderFactoryClass() { 
   
		return EnableAutoConfiguration.class;
	}

如上代码,自动配置核心的代码我都罗列出来了,最核心的就是loadFactoryNames方法,其主要有三步:

  1. 从classpath下获取所有META-INF/spring.factories这个文件下的信息。
  2. 将上面获取到的信息封装成Enumeration返回
  3. 遍历Enumeration,然后获取key为EnableAutoConfiguration下的所有值。
    META-INF/spring.factories 这类⽂件是什么就不懵了。当然在很多第三⽅依赖中
    都会有这个⽂件,⼀般每导⼊⼀个第三⽅的依赖,除了本⾝的jar包以外,还会有⼀个 xxx-spring-boot-autoConfigure,这个就
    是第三⽅依赖⾃⼰编写的⾃动配置类。我们现在就以 spring-boot-autocongigure 这个依赖来说下,其下面的META-INF/spring.factories文件。
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\

配置类注册到IOC容器的流程图

然后就是实例化这些配置类注册到IOC容器中。流程如下:
在这里插入图片描述

以DataSourceAutoConfiguration进行说明

通过上面的方式,所有的自动配置类都被导进主配置类中,但是这么多的配置类,明显有很多我们平常是没有使用到的,没必要全部生效,下面我们以DataSourceAutoConfiguration配置类为例来看一下自动配置类是如何工作的:

@Configuration
@ConditionalOnClass({ 
    DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ 
    Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration { 
   

}

@Configuration 注解表明了DataSourceAutoConfiguration类是一个JavaConfig配置类。@ConditionalOnClass只有当classpath中存在DataSource类或者EmbeddedDatabaseType类时才启动这个配置。@EnableConfigurationProperties这个注解的作用是将将DataSource类注入到IOC容器中。@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })是要导入额外的配置DataSourcePoolMetadataProvidersConfiguration

DataSourceProperties 类

下面我们就来一个个看一下:首先是DataSourceProperties类:

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
		implements BeanClassLoaderAware, EnvironmentAware, InitializingBean { 
   

	private ClassLoader classLoader;

	private Environment environment;

	private String name = "testdb";


	private boolean generateUniqueName;


	private Class<? extends DataSource> type;


	private String driverClassName;

	private String url;
	
	}

DataSourceProperties 通过@ConfigurationProperties注解将配置文件的前缀为(spring.datasource)的配置信息与自身的属性绑定。所有在配置⽂件中能配置的属性都是在 xxxProperties 类中封装着;配置⽂件能配置什么就可以参照某个功能对应的这个属性
类。

DataSourcePoolMetadataProvidersConfiguration 类

@Configuration
public class DataSourcePoolMetadataProvidersConfiguration { 
   

	@Configuration
	@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
	static class TomcatDataSourcePoolMetadataProviderConfiguration { 
   
	}
	
	@Configuration
	@ConditionalOnClass(HikariDataSource.class)
	static class HikariPoolDataSourceMetadataProviderConfiguration { 
   

DataSourcePoolMetadataProvidersConfiguration 类是数据库连接池提供者的一个配置类。即classpath中存在org.apache.tomcat.jdbc.pool.DataSource.class则使⽤tomcat-jdbc连接池,如果classpath中存在 HikariDataSource.class则使⽤ Hikari连接池,如果存在org.apache.commons.dbcp.BasicDataSource.class则启用dbcp 连接池。

总结

  1. SpringBoot启动时会扫描项目所依赖的JAR包,寻找包含spring.factories文件的JAR包。
  2. 根据spring.factories配置加载EnableAutoConfiguration
    其中给容器中自动配置添加组件的时候,会从propeties类中获取配置文件中指定这些属性的值。xxxAutoConfiguration:⾃动配置类给容器中添加组件。xxxProperties:封装配置⽂件中相关属性。
  3. 根据@Conditional注解的条件,进行自动配置并将Bean注入Spring容器
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149019.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月16日 下午2:36
下一篇 2022年6月16日 下午2:36


相关推荐

  • matlab多重比较lsd法,多重比较法-LSD I 附赠统计学最全思维导图~[通俗易懂]

    matlab多重比较lsd法,多重比较法-LSD I 附赠统计学最全思维导图~[通俗易懂]原标题:多重比较法-LSDI附赠统计学最全思维导图~文末附赠统计学最全干货导图~前面我们讲了方差分析,方差分析主要是用于多组均值比较的,方差分析的结果是多组均值之间是否有显著性差异,但是这个显著性差异是整体的显著性差异,可是我们并不知道具体是哪些组之间有显著性差异。所以就有了我们今天的多重比较,目的就是为了获取具体哪些组之间有显著差异。多重比较法方法有很多种,这篇主要介绍一下比较常用的一种LS…

    2022年6月5日
    29
  • Ubuntu 远程桌面配置

    Ubuntu 远程桌面配置Ubuntu 远程桌面配置远程端配置这里的远程端指的是服务端 也就是被远程访问的那一端安装 xrdp 用于协议支持 sudoapt getinstallxr 安装 xface4 用户界面支持 sudoapt getinstallxf session xsessionsudo 配置可被远程访问

    2026年3月19日
    2
  • Tomcat7目录介绍

    Tomcat7目录介绍Tomcat7目录介绍版本7.082:目录解析:1.bin:存放启动和关闭Tomcat的命令的路径bin目录:*startup.bat启动TomcatTomcat启动后当在游览器输入:hhttp://localhost:8080进去Tomcat的页面*shoutdown停止Tomcat2.conf:存放Tomcat的配置,所有的Tomcat的配置都在该路径下设置

    2022年7月18日
    19
  • 举例说明随机函数的应用python_Python生成50个随机数

    举例说明随机函数的应用python_Python生成50个随机数摘要:下文讲述Python代码中seed()函数的简介说明,如下所示:seed()函数功能用于改变随机数生成器的种子,常用于其它随机函数之前运行此函数seed()函数语法seed.seed([x])———参数说明—-x:任意数字———返回值说明—-无返回值seed()函数注意事项:1.使用seed()函数需引入包random(importrandom)2.设置随…

    2025年5月28日
    4
  • eclipseUML工具

    eclipseUML工具
    EclipseUML2008-05-0522:05
    来源:lhttp://bach.yo2.cn/articles/category/artoftechnology/page/3
    对于UML工具,我用的并不是太深入,所以仅是对几款小型umltools,以及非专业umltools稍做评价,像RationalRose这种专业uml软件就不比较了。
     
    在选择方面个人比较偏向java,eclipse,逆向工程功能.
    1.MicrosoftVi

    2022年7月12日
    17
  • 安筱鹏:No Cloud, No Agent —— 拥抱智能体经济的崛起

    安筱鹏:No Cloud, No Agent —— 拥抱智能体经济的崛起

    2026年3月15日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号