文章目录 一.使用姿势二.运行原理
上篇文章中,《springboot源码(一)启动流程+自动配置原理分析》,简单分析了启动流程,其中涉及到了@SpringBootApplication注解,本文针对其中的exclude属性的作用及其原理,进行分析。
一.使用姿势
比如我的工程里引入的elasticsearch的依赖,使用了es的功能,但是有时我的es环境没准备好,但是我想启用项目,这时就会报错,那么我就可以将es相关的配置exclude掉,这个springboot在启动的时候就不去连接配置es了。
活着排除DataSourceAutoConfiguration,因为这个是自动配置单数据源的,如果你想配置多数据源,那么就需要把这个排除掉,然后自己单独配置多数据源。
exclude参数使用:
@SpringBootApplication (exclude = {DataSourceAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class,DataSourceAutoConfiguration.class})public class Demo1Application {@SpringBootApplication注解排除参数,不光支持exclude,还有一个excludeName,源码如下:
public @interface SpringBootApplication {/** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};/** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};excludeName参数使用:
@SpringBootApplication(excludeName = {"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration", "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"})也可以exclude和excludeName同时混合使用。
二.运行原理首先,@SpringBootApplication注解继承了@EnableAutoConfiguration,同时exclude和excludeName参数使用了@AliasFor修饰,意味着我们给@SpringBootApplication指定exclude属性值的时候,相当于给@EnableAutoConfiguration的exclude参数也指定了相同的值。
springboot的自动配置注解,@EnableAutoConfiguration注解中Import了AutoConfigurationImportSelector.class,其中的如下方法中:
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}//获取注解中的所有属性,也就是exclude和excludeNameAnnotationAttributes attributes = getAttributes(annotationMetadata);//获取spring-boot-autoconfigure包中,spring.factories中的配置类List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);//去除重复的配置类configurations = removeDuplicates(configurations);//去除已经排除掉的Set<String> exclusions = getExclusions(annotationMetadata, attributes);//校验是否是有效排除checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);//去除不符合condition条件的configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}说明:
1.getCandidateConfigurations(annotationMetadata,attributes); 获取到了spring-boot-autoconfigure包中,spring.factories中,key为spring-boot-autoconfigure包中,spring.factories中的配置类的配置类,总共118个;
2.getExclusions(annotationMetadata, attributes);获取已经被排除的类;
3.removeAll(exclusions); 从集合中排除exclusions
打开方法看下:
protected Set<String> getExclusions(AnnotationMetadata metadata,AnnotationAttributes attributes) {Set<String> excluded = new LinkedHashSet<>();excluded.addAll(asList(attributes, "exclude"));excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));excluded.addAll(getExcludeAutoConfigurationsProperty());return excluded;}很简单,就是把exclude的值和excludeName的值拿出来放到set集合中返回。
总结,springboot会扫描spring.factories配置文件中的配置类,保存到集合,然后在扫描exclude和excludeName中配置的类,将其总集合中排除即可。