Spring Boot的自动配置原理

本文深入探讨了Spring Boot的自动配置机制,包括如何通过@EnableAutoConfiguration注解找到并加载自动配置类,以及配置文件如何影响自动配置类的生效。详细解析了AutoConfigurationImportSelector的工作流程,如何从spring.factories文件中获取配置类,并根据条件判断哪些配置类生效。同时,文章介绍了@ConfigurationProperties注解如何将配置文件的属性绑定到Bean中,以及@Conditional注解家族在条件判断中的作用。通过一个HttpEncodingAutoConfiguration的例子,阐述了自动配置如何根据配置文件内容创建和管理Bean。最后,提到了通过设置debug=true查看自动配置报告的方法,帮助开发者理解Spring Boot应用的配置情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、获取有效自动配置类

2、自动配置生效


配置文件到底能写什么?怎么写?自动配置原理;

配置文件能配置的属性参照

1、获取有效自动配置类

.@SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot需要运行这个类的main方法来启动SpringBoot应用;

SpringBootApplication 

@Target(ElementType.TYPE) 设置当前注解可以标记在哪(类、方法等)

@Retention(RetentionPolicy.RUNTIME) 当注解标注的类编译以什么方式保留

        RetentionPolicy.RUNTIME----会被jvm加载

@Documented java doc 会生成注解信息

@Inherited 是否会被继承

@SpringBootConfiguration:Spring Boot的配置类;

   标注在某个类上,表示这是一个Spring Boot的配置类;

   @Configuration:配置类上来标注这个注解;

         配置类 ----- 配置文件;

        配置类也是容器中的一个组件;@Component

@ComponentScan : 扫描包 相当于在spring.xml 配置中<context:comonent-scan>  但是并没有指定basepackage,如果没有指定spring底层会自动扫描当前配置类所有在的包

        TypeExcludeFilter:springboot对外提供的扩展类, 可以供我们去按照我们的方式进行排除

        AutoConfigurationExcludeFilter:排除所有配置类并且是自动配置类中里面的其中一个

@EnableAutoConfiguration:开启自动配置功能;

   以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置,会帮我们自动去加载 自动配置类

这个注解里面,最主要的就是@EnableAutoConfiguration,这么直白的名字,一看就知道它要开启自动配置,SpringBoot要开始骚了,于是默默进去@EnableAutoConfiguration的源码。

@AutoConfigurationPackage : 将当前配置类所在包保存在BasePackages的Bean中。供Spring内部使用,

 就是注册了一个保存当前配置类所在包的一个Bean

@Import(AutoConfigurationImportSelector.class) 关键点!

可以看到,在@EnableAutoConfiguration注解内使用到了@import注解来完成导入配置的功能,而AutoConfigurationImportSelector实现了DeferredImportSelector;Spring内部在解析@Import注解时会调用getAutoConfigurationEntry方法

DeferredImportSelector工作原理:

判断有没有实现getImportGroup()方法,没有的话执行selectImports返回一个数组,将数组中的完整类名注册为Bean;有的话要返回一个自定义的实现DeferredImportSelector.Group的类,然后执行这个类中的process和selectimports方法

启动application时,走到了AutoConfigurationImportSelector的getImportGroup方法

 返回了一个自定义的实现DeferredImportSelector.Group的类AutoConfigurationGroup

 接下来会执行process方法

 调用getAutoConfigurationEntry方法获取所有有效的配置类

 调用getCandidateConfigurations获取所有配置类

 此方法有调用getSpringFactoriesLoaderFactoryClass,

 

拿到EnableAutoConfiguration作为参数传入SpringFactoriesLoader.loadFactoryNames

 

loadSpringFactories去读取存放配置类的文件META-INF/spring.factories,会去所有jar包和类路径去读取这个文件

其实这个方法在之前已经调用过了,是在new SpringApplication 时调用的,会将读出来的结果放到缓存中

 其中和自动装配相关的spring.factories

 

loadSpringFactories会得到所有的配置类

 之后调用getOrDefault 根据EnableAutoConfiguration 过滤

 拿到所有的自动配置类

getCandidateConfigurations返回的就是所有的自动配置类,就是帮我们整合第三方库做的默认配置

 之后会调用这个方法

 根据pom依赖中添加的starter过滤出有效的自动配置类

每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;

所有自动配置类表

后续:这个@EnableAutoConfiguration注解通过@SpringBootApplication被间接的标记在了Spring Boot的启动类上。在SpringApplication.run(...)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中。

2、自动配置生效(配置文件关联配置类)

以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

@Configuration(proxyBeanMethods = false)

  • 标记了@Configuration Spring底层会给配置创建cglib动态代理。 作用:就是防止每次调用本类的Bean方法而重新创建对象,Bean是默认单例的

这里proxyBeanMethods = false 表示调用本类的Bean方法会重新创建对象,可以理解为时多例的

@EnableConfigurationProperties(ServerProperties.class)  开启配置属性

  • 启用可以在配置类设置的属性 对应的类

它后面的参数是一个ServerProperties类,这就是习惯优于配置的最终落地点。

在这个类上,我们看到了一个非常熟悉的注解:@ConfigurationProperties,它的作用就是从配置文件中绑定属性到对应的bean上,而@EnableConfigurationProperties负责导入这个已经绑定了属性的bean到spring容器中(见上面截图)。那么所有其他的和这个类相关的属性都可以在全局配置文件中定义,也就是说,真正“限制”我们可以在全局配置文件中配置哪些属性的类就是这些XxxxProperties类,它与配置文件中定义的prefix关键字开头的一组属性是唯一对应的。

至此,我们大致可以了解。在全局配置的属性如:server.port等,通过@ConfigurationProperties注解,绑定到对应的XxxxProperties配置实体类上封装为一个bean,然后再通过@EnableConfigurationProperties注解导入到Spring容器中。

而诸多的XxxxAutoConfiguration自动配置类,就是Spring容器的JavaConfig形式,作用就是为Spring 容器导入bean,而所有导入的bean所需要的属性都通过xxxxProperties的bean来获得。

@ConditionalOnBean:当容器里有指定的bean的条件下。

@ConditionalOnMissingBean:当容器里不存在指定bean的条件下。

@ConditionalOnClass:当类路径下有指定类的条件下。

@ConditionalOnMissingClass:当类路径下不存在指定类的条件下。

@ConditionalOnProperty:指定的属性是否有指定的值,比如@ConditionalOnProperties(prefix=”spring.http.encoding”, value=”enable”, matchIfMissing=true)

其中prefix指定了配置的统一前缀“spring.http.encoding”,而value指定了具体的属性名称为“enabled”。这里并没有设置havingValue的值,如果havingValue未指定值,默认情况下在属性配置中设置的值为true则生效(如上配置),false则不生效。

@ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true")

//prefix为配置文件中的前缀, //name为配置的名字 //havingValue是与配置的值对比值,当两个值相同返回true,配置类生效.

@Conditionalxxx根据当前不同的条件判断,决定这个配置类是否生效?

@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

@Conditional扩展注解作用

(判断是否满足当前指定条件)

@ConditionalOnJava

系统的java版本是否符合要求

@ConditionalOnBean

容器中存在指定Bean;

@ConditionalOnMissingBean

容器中不存在指定Bean;

@ConditionalOnExpression

满足SpEL表达式指定

@ConditionalOnClass

系统中有指定的类

@ConditionalOnMissingClass

系统中没有指定的类

@ConditionalOnSingleCandidate

容器中只有一个指定的Bean,或者这个Bean是首选Bean

@ConditionalOnProperty

系统中指定的属性是否有指定的值

@ConditionalOnResource

类路径下是否存在指定资源文件

@ConditionalOnWebApplication

当前是web环境

@ConditionalOnNotWebApplication

当前不是web环境

@ConditionalOnJndi

JNDI存在指定项

我们怎么知道哪些自动配置类生效;

我们可以通过设置配置文件中:启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;

 

细节

一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;

所有在配置文件中能配置的属性都是在xxxxProperties类中封装;配置文件能配置什么就可以参照某个功能对应的这个属性类

还记得这个过滤器吧, 对,就是我们以前设置编码的, 我们现在不需要去web.xml配置过滤器了, 只需要往容器中注入该过滤器。它的值都是通过properties设置的

 

比如需要配置编码那就可以推算出

properties.getServlet().getEncoding().setCharset(UTF_8); 就等于如下配置:

properties= server 为什么呢? 因为 ServerProperties 上面有个注解@ConfigurationProperties(prefix = "server") 已经设置名为server

getServlet()= servlet

getEncoding()=encoding

setCharset(UTF_8)= charset=UTF-8

server.servlet.encoding.charset=UTF-8

所以只有知道了自动配置的原理及源码 才能灵活的配置SpringBoot

一定要记得XxxxProperties类的含义是:封装配置文件中相关属性;XxxxAutoConfiguration类的含义是:自动配置类,目的是给容器中添加组件。

简单总结:可以分为两步,1、获取有效自动配置类2、自动配置生效

Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载,而这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个JavaConfig形式的Spring容器配置类,它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:server.port,而XxxxProperties类是通过@ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。

自动配置流程图

https://www.processon.com/view/link/5fc0abf67d9c082f447ce49b

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值