教你如何自定义标准的SpringBootstarter,真的很清楚一次实现这些功能,并根据需要将它们包含到我们要构建的任何应用程序中是可以被多个项目或模块使用的内容。例如,一个SDK在SpringBoot中。用于表示提供这种横切关注点的模块的术语是启动器。依靠启动器,您可以轻松使用它包含的一些功能,不管你在工作中会不会构建自己的starter,你一定要有构建“starter”的想法。本文将结合SpringBoot官方标准搭建一个简单的启动器。自定义启动器。在我们详细了解如何自定义starter之前,为了更好的理解我们每一步都做了什么以及starter是如何工作的,我们先从宏观的角度来看一下starter的结构。通常一个完整的starter需要包含以下两个组件:Auto-ConfigureModuleStarterModule如果看到下面两个组件的解释有些抽象,就可以有个大概的了解。读完这篇文章,回过头来就会豁然开朗。Auto-ConfigureModuleAuto-ConfigureModule(自动配置模块)是一个包含自动配置类或Gradle模块的Maven。通过这种方式,我们可以构建可以自动为应用程序上下文做出贡献的模块,以及添加特定功能或提供对某些外部库的访问。StarterModuleSpringBootStarter是一个Maven或Gradle模块,其唯一目的是提供“启动”功能所需的所有依赖项。可以包含一个或多个自动配置模块依赖项,以及可能需要的任何其他依赖项。这样,在Springboot应用中,我们只需要添加这个starter依赖就可以使用它的特性:Spring官方参考手册推荐将自动配置分离,将每个自动配置启动到单独的Maven或Gradle模块中,这样独立的自动配置和依赖管理。如果你没有一个上万用户的开源库,你也可以把两者合并成一个模块你可以将auto-configurationcode和thatdependencymanagement合并在一个模块中如果你不需要分开thosetwoconcerns命名来自Spring官方的starters都是以spring-boot-starter开头的,例如:spring-boot-starter-webspring-boot-starter-aop如果我们自定义starter函数名为acme,那么我们的名字是这样的:acme-spring-boot-starteracme-spring-boot-autoconfigure如果在starter中使用配置键,还要注意不要使用SpringBoot使用的命名空间,比如(server,management,spring)ParentModulecreation首先我们看一下全局的项目结构:一级目录结构:.├──pom.xml├──rgyb-spring-boot-autoconfigure├──rgyb-spring-boot-sample└──rgyb-spring-boot-starter二级目录结构:.├──pom.xml├──rgyb-spring-boot-自动配置│├──pom.xml│└──src├──rgyb-spring-boot-sample│├──pom.xml│└──src└──rgyb-spring-boot-starter├──pom.xml└──src创建一个空的parentMavenModule,主要提供依赖管理,让SubModule做不需要单独维护依赖版本号。查看pom.xml的内容:org.springframework.bootspring-boot-dependencies${spring-boot.version}pomimportAuto-ConfigureModule新建一个classGreetingAutoConfiguration@ConfigurationpublicclassGreetingAutoConfiguration{@BeanpublicGreetingServicegreetingService(GreetingPropertiesgreetingProperties){returnnewGreetingService(greetingProperties.);}}我们使用@Configuration注解将类GreetingAutoConfiguration标记为starter的入口此配置包含我们提供入门功能所需的所有@Bean定义。在本例中,为了简单说明问题,我们只在应用上下文GreetingService中添加了GreetingServiceBean。内容如下:@AllArgsConstructorpublicclassGreetingService{privateListmembers=newArrayList<>();publicvoidsayHello(){members.forEach(s->System.out.println("hello"+s));}}创建在resources目录新建一个文件META-INF/spring.factories(如果目录META-INF没有需要手动创建),在文件中写入内容:org.springframework.boot.autoconfigure.EnableAutoConfiguration=\top.dayarch.autoconfigure.GreetingAutoConfigurationSpring启动时,会加载其类路径下的所有spring.factoreis文件,并加载里面的声明,配置完成后,GreetingAutoConfiguration类就准备好了,我们的SpringBootStarter就有了一个自动激活的入口点。到这里这个“不完整的启动器”就可以使用了。但是因为是自动激活的,为了让它灵活好用,我们需要让它按照我们的意愿来激活和使用,所以我们需要条件注解来帮助条件配置在类中添加两个条件注解:@Configuration@ConditionalOnProperty(value="rgyb.greeting.enable",havingValue="true")@ConditionalOnClass(DummyEmail.class)publicclassGreetingAutoConfiguration{...}通过使用@ConditionalOnProperty注解,我们告诉Spring只有属性rgyb.greeting.enable应该设置为trueGreetingAutoConfiguration(及其声明的所有bean)仅通过使用@ConditionalOnClass注释包含在应用程序上下文中,如果类DummyEmail.class存在,我们告诉Spring仅包含GreetingAutoConfiguration(及其声明的所有bean)在类路径上应用程序上下文中的多个条件是和/和关系。GreetingAutoConfiguration只会在满足所有条件时加载。如果对条件注解的使用不是很清楚,可以查看我之前的文章:@Conditional注解,灵活配置SpringBoot配置属性管理上面使用了@ConditionalOnProperty注解。实际启动器中可能有很多属性,所以我们需要集中管理这些属性:@Data@ConfigurationProperties(prefix="rgyb.greeting")publicclassGreetingProperties{/***GreetingPropertiesswitch*/booleanenable=false;/***需要打招呼的成员列表*/Listmembers=newArrayList<>();}我们知道application.yml中要用到这些属性是的,当我们需要使用这些属性的时候,为了让IDE给出更友好的提示,我们需要在pom.xml中添加依赖:org.springframework.bootspring-boot-configuration-processortrue这样,当我们mvn编译时,会生成一个名为spring-configuration-metadata.json的JSON文件。文件内容如下:Generated内容在后面的内容中用到,看改善启动时间对于类路径上的每个自动配置类,SpringBoot都要计算@Conditional...条件值,它用于决定是否加载自动配置及其需要的所有类,这取决于Springboot应用程序中启动器的大小和数量,这可能是一个非常昂贵的操作,并且会影响启动时间。为了改善启动时间,我们需要在pom.xml中添加另一个依赖:org.springframework.bootspring-boot-autoconfigure-processortrue该注解会生成一个名为spring-autoconfigure-metadata.properties的属性文件,其内容如下:这样,SpringBoot在启动时读取这些元数据,可以过滤掉配置不满足条件的不实际检查这些类,以提高启动速度。至此,Auto-ConfigureModule构建完毕。我们需要继续完成StarterModule的构建StarterModuleConstructionStarterModule的构建非常简单,你可以认因为它是一个空模块,除了依赖Auto-ConfigureModule之外,它唯一的作用就是提供使用starter特性所需的所有依赖,所以我们在starter模块的pom.xml文件中添加如下内容:<依赖项>top.dayarch.learningsrgyb-spring-boot-autoconfigure1.0.0.RELEASE同时在resources目录下新建一个文件META-INF/spring.providers,内容如下:providers:rgyb-spring-boot-autoconfigure这个文件的主要作用是解释starter模块的依赖信息,多个依赖用逗号分隔。该文件不会影响启动器的使用。入门模块可以这么简单。mvninstall这两个模块到本地MavenRepository。接下来,我们创建一个示例模块来导入此启动器依赖项将从本地Maven存储库中提取以创建一个示例模块。我们通常可以通过SpringInitializr初始化一个SpringBoot项目(rgyb-spring-boot-sample),引入我们刚刚创建的starter依赖,在samplepom.xml中添加依赖:top.dayarch.learningsrgyb-spring-boot-starter1.0.0.RELEASE接下来配置application.yml属性rgyb:greeting:enable:truemembers:-李磊-韩梅梅当我们配置YAML时,会出现如下提示,所以会更友好。当然,为了规范起见,最好用英文描述属性。这里用中文描述来说明问题:写一个测试类,写一个测试用例:@Autowired(required=false)privateGreetingServicegreetingService;@TestpublicvoidtestGreeting(){greetingService.sayHello();}测试结果如下:你好李雷你好韩梅梅总结到这里,完整的starter开发就结束了,希望大家了解它的构建过程,目录结构和命名标准,以便大家开发自己的当你有相应的业务需求时,其他人使用了starter,开发了starter。其他的可以手动添加依赖,引入starter的相关功能。那我们如何才能像SpringInitializr那样通过下拉菜单来选择我们的starter,从而直接初始化整个项目呢。下一篇文章中,我们将模仿SpringInitializr自定义自己的Initializr知识点来讲解Dependencyoptional。为什么Auto-ConfigureModule的依赖都是optional=true?这就涉及到Maven传递依赖的问题。详细请看MavenDependencyTransit深入了解spring.factoriesSpringBoot是如何加载这个文件并找到我们的配置类的。下图是SpringBoot应用启动的部分调用栈。我添加了一个断点:打开SpringFactoriesLoader类,这就是你所看到的:这两张图应该足以说明问题。是SPI的一种加载方式。更多详情请自行了解。实际案例建议在这里查看mybatis-spring-boot-starter这不是Spring官方的案例,从中我们:模仿它的目录结构模仿它的设计理念模仿它的编码规范另外,我已经上传了这篇文章的案例,公众号回复“demo”,打开链接,查看customstarter目录下的内容询问为什么生成spring的时候没有包含@ConditionalOnProperty的内容-autoconfigure-metadata.properties文件中写进去如果我们要上传依赖到远程中央仓库,你知道如何搭建自己的maven仓库吗?你的灯还亮着吗?