SpringBoot的starter到底是什么?( 五 )

门面模式,其他业务系统想引入相应的功能,必须要通过这个门面 。
我们重点分析一下 id-generate-autoconfiguration.jar
该jar包核心内容是:IdGenerateConfiguration,这个配置类中创建了IdGenerateService对象 , IdGenerateService是我们所需要自动配置的具体功能 。
接下来一个最重要的问题:IdGenerateConfiguration为什么会自动加载的呢?
还记得我们定义的spring.factories文件不?
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sue.IdGenerateAutoConfiguration它里面只包含一行配置,其中keyEnableAutoConfigurationvalueIdGenerateAutoConfiguration
要搞明白这个过程,要从Application类的@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 {};}从上面可以看出该注解里面包含了@EnableAutoConfiguration注解 。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};}@EnableAutoConfiguration注解会引入AutoConfigurationImportSelector类 。
该类的selectImports方法一个关键方法:
@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {//配置有没有配置spring.boot.enableautoconfiguration开关 , 默认为true//如果为false,则不执行自动配置的功能,直接返回if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}//找spring-autoconfigure-metadata.properties中的元素AutoConfigurationMetadata autoConfigurationMetadata = https://www.huyubaike.com/biancheng/AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);//获取EnableAutoConfiguration注解中的属性AnnotationAttributes attributes = getAttributes(annotationMetadata);//获取工程下所有配置key为EnableAutoConfiguration的值,即IdGenerateConfiguration等类 。List configurations = getCandidateConfigurations(annotationMetadata,attributes);//删除重复的值configurations = removeDuplicates(configurations);//获取需要排除的规则列表Set exclusions = getExclusions(annotationMetadata, attributes);//检查checkExcludedClasses(configurations, exclusions);//删除需要排除的值configurations.removeAll(exclusions);//根据配置文件中配置的开关 , 过滤一部分不满足条件的值configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return StringUtils.toStringArray(configurations);}这里就是starter能够自动配置的秘密
此外,有些朋友看其他人定义的springboot starter可能会有疑惑 。
先看看druid-spring-boot-starter

SpringBoot的starter到底是什么?

文章插图
alibaba定义的druid-spring-boot-starter只有xxx-spring-boot-starter.jar文件,而没有xxx-spring-boot-autoconfigure.jar文件 。
再看看spring-boot-starter-jdbc
SpringBoot的starter到底是什么?

文章插图
更神奇的是这个文件中连pom.xml都没有 , 一脸懵逼 。。。。。。。
是不是我讲错了?
答:其实没有 。
SpringBoot的原则是约定优于配置
从spring-boot-starter-jdbc内部空实现来看,它的约定是要把xxx-spring-boot-starter.jar和xxx-spring-boot-autoconfigure.jar区分开的 。个人认为,alibaba定义得并不好 , 没有遵照springboot的约定,虽然功能不受影响 。(这个地方欢迎一起探讨一下)
而springboot自己定义的spring-boot-starter-jdbc为什么连pom.xml文件也没有呢?
它不需要依赖xxx-spring-boot-autoconfigure.jar文件吗?
因为springboot把所有的自动配置的类都统一放到spring-boot-autoconfigure.jar下面了:

推荐阅读