我们在使用SpringBoot的时候,经常会在pom.xml中加入一系列的依赖,然后启动一个包含main方法的Application,就一切OK了。对你我来说,感觉就像我想自己做一道菜。我不再需要准备每一部分的原材料。我可以直接买一个包装好的菜的原料,放到锅里。那我们就来仔细看看这个“包装好的”原材料都做了些什么。AddStarterdependencies这里添加的依赖,除了我们之前在Maven中熟悉的,有的是这样的:命名为xxx-starter,比如org.springframework.bootspring-boot-starter-weborg.mybatis.spring.bootmybatis-spring-boot-starter1.3.2这些启动器如何工作?他们什么时候开始工作的?一切从入口开始。我们以上面的starter为例,看这个mybatisstarter,它对应的pom包含这些依赖org.springframework.bootspring-boot-starterorg.springframework.bootspring-boot-starter-jdbcorg.mybatis.spring.boot复制代码mybatis-spring-boot-autoconfigureorg.mybatismybatisorg.mybatismybatis-spring我们看到相当于添加了一个Starter依赖,后面会引入很多其他的依赖吧定义通过Maven的传递依赖自动添加。相对于传统的依赖,自动配置包括这样一个:mybatis-spring-boot-autoconfigure,这也是每个Starter的秘密:“AutoConfigure”,在实现的时候会考虑应用中的其他因素,“推断”你需要的弹簧配置。在SpringBoot中,我们最好的感受就是好像配置好了,直接拿来用。这是spring-boot-autoconfigure。每个starter都有一个名为spring.factories的文件,存放在META-INF目录下,内容类似如下:#AutoConfigureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration所有需要自动配置的类都需要配置为key是EnableAutoConfiguration的。我们来看看类的内部结构publicclassMybatisAutoConfiguration类上,有很多注解来标识,有几点需要注意:其中有标准的Spring配置注解@Configuration@ConditionalXX来标识@AutoConfigureAfter的执行顺序,其中@ConditionalOnClass表示当SqlSessionFactory类存在时执行配置,当@ConditionalOnBean在SpringContext中识别到DataSourceBean时,执行配置。这些spring.factories是如何识别的?这不得不夸一下Spring的FactoriesLoader。查看自动配置类是常规Spring{@linkConfiguration}beans的官方文档。它们使用{@linkSpringFactoriesLoader}机制定位(针对此类)。通常,自动配置bean是{@linkConditional@Conditional}bean(最常使用{@linkConditionalOnClass@ConditionalOnClass}和{@linkConditionalOnMissingBean@ConditionalOnMissingBean}注释)。启动时根据ClassLoader中的jar扫描所有的spring.factories,过滤掉符合条件的,执行相应的配置。重点可以关注下protectedListgetAutoConfigurationImportFilters(){returnSpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class,this.beanClassLoader);}AutoConfigurationMetadataautoConfigurationMetadata){longstartTime=System.nanoTime();String[]candidates=StringUtils(anconfigtoStringAroles);[]skip=newboolean[candidates.length];booleanskipped=false;for(AutoConfigurationImportFilterfilter:getAutoConfigurationImportFilters()){invokeAwareMethods(filter);boolean[]match=filter.match(candidates,autoConfigurationMetadata);for(inti=0;iresult=newArrayList<>(candidates.length);for(inti=0;i(result);}publicString[]selectImports(AnnotationMetadataannotationMetadata){if(!isEnabled(annotationMetadata)){returnNO_IMPORTS;}AutoConfigurationMetadataautoConfigurationMetadata=AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AnnotationAttributesattributes=getAttributes(annotationMetadata);Listconfigurations=getCandidateConfigurations(annotationMetadata,attributes);configurations=removeDuplicates(configurations);设置排除项=getExclusions(annotationMetadata,attributes);checkExcludedClasses(configurations,exclusions);configurations.removeAll(exclusions);configurations=filter(configurations,autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations,exclusions);之后filter方法过滤掉符合条件的。创建自定义Starter经过上面两步,我们大概知道了Starter的工作原理。有时候,当我们需要对外提供一些工具组件的时候,我们也想以Starter的形式提供给其他人使用。步骤还算清楚,就像一幅葫芦画。首先创建自己的模块并添加所需的依赖项。创建对应的AutoConfiguration类,创建META-INF/spring.factories文件。此时,您不需要使用SpringBoot作为Parent依赖项。添加org.springframework.bootspring-boot-autoconfigure2.0.6.RELEASEorg.springframework.bootspring-boot-starter2.0.6.RELEASEAutoConfiguration类也很简单,创建一个@Configuration@ConditionalOnClass(HelloService.class)publicclassHelloServiceAutoConfiguration{然后在需要这个服务的地方添加org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.demo.HelloServiceAutoConfiguration文件,直接引入依赖即可。【本文为专栏作家“侯书城”原创稿件,转载请通过作者微信公众号“Tomcat物语”获得授权】点此查看本作者更多好文