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

它实现了ApplicationRunner接口,所以在springboot启动的时候会调用该类的run方法 。
好了,所有自定义starter的代码和测试代码都已经就绪 。接下,运行一下Application类的main方法 。
运行结果:
176完美,验证成功了 。
接下来,我们分析一下starter的底层实现原理 。
4 starter的底层原理是什么?通过上面编写自己的starter的例子,相信大家对starter的认识更进一步了,现在跟大家一起看看starter的底层是如何实现的 。
id-generate-starter.jar其实是一个空项目,依赖于id-generate-autoconfiguration.jar 。
id-generate-starter.jar是一个入口,我们给他取一个更优雅的名字:门面模式,其他业务系统想引入相应的功能,必须要通过这个门面 。
我们重点分析一下 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);}

经验总结扩展阅读