自动配置原理
一句话总结就是@EnableAutoConfiguration把xxxAutoConfiguration都加到容器中,每一个xxxAutoConfiguration都有自己的自动配置功能;然后xxxAutoConfiguration类又为自己对应的xxxxProperties开启ConfigurationProperties功能,配置类就为容器添加组件。
开启自动配置功能
1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
应用程序启动,从主程序的@SpringBootApplication注解开始
@EnableAutoConfiguration
- 把xxxAutoConfiguration这样的自动配置类加入到容器中
@EnableAutoConfiguration 注解通过@Import({AutoConfigurationImportSelector.class})将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值(各种类)注入到了容器中,即xxxAutoConfiguration - 每一个自动配置类进行自动配置功能
将自动配置类加入容器@Import({AutoConfigurationImportSelector.class})
@EnableAutoConfiguration利用AutoConfigurationImportSelector给容器中导入一些组件,具体就是最终就是将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;也就是xxxAutoConfiguration,这些都是用来做自动配置的
selectImports
AutoConfigurationImportSelector的selectImports方法:
返回的String数组里定义的全限类名都会被Spring容器加载
-
getAutoConfigurationEntry 方法获取候选的配置
-
getCandidateConfigurations
-
SpringFactoriesLoader.loadFactoryNames
从类路径下得到资源
①扫描所有jar包类路径的META-INF/spring.factories
②得到这些的url,然后遍历这些url包装成一个properties对象
③从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中
最终是将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;
也就是xxxAutoConfiguration,这些都是用来做自动配置的
自定义start组件整合到spring boot
当我们开发了一个和spring boot完全无关的组件,想要整合到spring boot中的话,即让springboot容器能够加载我们自定义的组件,我们就自定了了一个start组件用来将我们自定义的组件和springboot整合。
这个start组件的入口就是AppConfig类,只要我们将AppConfig加入到了Spring容器,那就相当于把自定义组件和SpringBoot整合成功,这就需要用Spring Boot的自动配置原理。
加入到容器中的方式就是将AppConfig写到当前项目的/META-INF/spring.factories 配置文件里,springboot就会扫描到
每一个自动配置类进行自动配置功能
以HttpEncodingAutoConfiguration为例
条件判断
首先看HttpEncodingAutoConfiguration上的注解
主要就是声明这是一个配置类,并且开启自己对应的属性类ServerProperties的ConfigurationProperties功能。 然后指定了当前配置类生效的条件
@Configuration
表示这是一个配置类@EnableConfigurationProperties({ServerProperties.class})
启动指定类的
ConfigurationProperties功能;并把HttpEncodingProperties加入到ioc容器中将配置文件中对应的值和HttpEncodingProperties绑定起来;- @Conditional 注解相关的 条件
Spring底层@Conditional注解,根据不同的条件,如果
满足指定的条件,整个配置类里面的配置就会生效;
所以下面三个都是需要满足的条件
@ConditionalOnWebApplication
断当前应用是否是web应用,如果是,当前配置类生效@ConditionalOnClass({CharacterEncodingFilter.class})
判断当前项目有没有这个类
CharacterEncodingFilter(SpringMVC中进行乱码解决的过滤器)@ConditionalOnProperty
(
prefix = “server.servlet.encoding”,
value = {“enabled”},
matchIfMissing = true
) 判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
给容器添加组件
一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取
的,这些类里面的每一个属性又是和配置文件绑定的;
属性类ServerProperties
HttpEncodingAutoConfiguration上的@EnableConfigurationProperties注解 启动了指定类ServerProperties的ConfigurationProperties功能
@EnableConfigurationProperties({ServerProperties.class})
通过原理得到SpringBoot的使用方式
1)、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这
些属性的值;
xxxxAutoConfigurartion:自动配置类;
给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
@Conditional派生注解
@Conditional是Spring的注解,作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
SpringBoot 对@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
,来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;