一、什么是Starter?

在开发过程中我们就经常使用到各种starter,比如mybatis-spring-boot-starter,只需要进行简单的配置即可使用,就像一个插件非常方便。这也是SpringBoot非常重要的一个特性——自动化配置。

二、实现

2.1创建一个maven项目并配置pom.xml

命名规范: Spring官方的Starter命名格式一般是spring-boot-starter-{name},比如spring-boot-starter-web 。而非官方的,官方建议artifactId命名应该遵循 {name}-spring-boot-starter的格式,如example-spring-boot-starter。

pom文件

  1. <?xml version="1.0" encoding="UTF-8"?> 

  2. <project xmlns="http://maven.apache.org/POM/4.0.0" 

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 

  5. <modelVersion>4.0.0</modelVersion> 


  6. <groupId>cn.sp</groupId> 

  7. <artifactId>example-spring-boot-starter</artifactId> 

  8. <version>1.0-SNAPSHOT</version> 


  9. <properties> 

  10. <spring-boot.version>2.1.5.RELEASE</spring-boot.version> 

  11. </properties> 


  12. <dependencies> 

  13. <dependency> 

  14. <groupId>org.springframework.boot</groupId> 

  15. <artifactId>spring-boot-configuration-processor</artifactId> 

  16. <optional>true</optional> 

  17. </dependency> 


  18. <dependency> 

  19. <groupId>org.springframework.boot</groupId> 

  20. <artifactId>spring-boot-autoconfigure</artifactId> 

  21. </dependency> 

  22. </dependencies> 



  23. <dependencyManagement> 

  24. <dependencies> 

  25. <dependency> 

  26. <!-- Import dependency management from Spring Boot --> 

  27. <groupId>org.springframework.boot</groupId> 

  28. <artifactId>spring-boot-dependencies</artifactId> 

  29. <version>${spring-boot.version}</version> 

  30. <type>pom</type> 

  31. <scope>import</scope> 

  32. </dependency> 

  33. </dependencies> 

  34. </dependencyManagement> 


  35. </project> 

spring-boot-configuration-processor 的作用是编译时生成 spring-configuration-metadata.json ,此文件主要给IDE使用,ctlr+鼠标左键点击配置文件(如application.properties)上相关配置属性,即可跳转到配置此属性的类中。

我们要实现的一个小功能是读取配置文件上cn.sp.config的字符串,然后按照给定的分隔符进行分割。

2.2编写配置文件读取类

@ConfigurationProperties(prefix = "cn.sp")
public class StarterServiceProperties { private String config; public String getConfig() {
return config;
} public void setConfig(String config) {
this.config = config;
}
}

2.3编写Service

public class StarterService {

    private String config;

    public StarterService(String config){
this.config = config;
} public String[] split(String separatorChar){ return this.config.split(separatorChar);
}
}

2.4编写自动配置类(重点)

  1. package cn.sp.autoconfigure; 


  2. import org.springframework.beans.factory.annotation.Autowired; 

  3. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 

  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 

  5. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 

  6. import org.springframework.boot.context.properties.EnableConfigurationProperties; 

  7. import org.springframework.context.annotation.Bean; 

  8. import org.springframework.context.annotation.Configuration; 


  9. /** 

  10. * Created by 2YSP on 2019/5/22. 

  11. */ 

  12. @Configuration 

  13. @ConditionalOnClass(StarterService.class) 

  14. //@ConditionalOnProperty(prefix = "cn.sp",value = "enable",matchIfMissing = true) 

  15. @EnableConfigurationProperties(StarterServiceProperties.class) 

  16. public class StarterAutoConfigure { 


  17. @Autowired 

  18. private StarterServiceProperties properties; 


  19. @Bean 

  20. @ConditionalOnMissingBean 

  21. @ConditionalOnProperty(prefix = "cn.sp",value = "enabled",havingValue = "true") 

  22. StarterService starterService(){ 

  23. return new StarterService(properties.getConfig()); 







说下这几个注解的作用:

  1. @ConditionalOnClass:当classpath下发现该类的情况下进行自动配置。
  2. @EnableConfigurationProperties:使使用 @ConfigurationProperties 注解的类生效。具体可以参考https://www.jianshu.com/p/7f54da1cb2eb
  3. @ConditionalOnMissingBean:当Spring上下文中不存在该Bean时生效。
  4. @ConditionalOnProperty(prefix = "cn.sp",value = "enabled",havingValue = "true"),当配置文件中cn.sp.enabled=true时有效。

下面列举SpringBoot中的所有@Conditional注解及作用

@ConditionalOnBean:当容器中有指定的Bean的条件下
@ConditionalOnClass:当类路径下有指定的类的条件下
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean:当容器中没有指定Bean的情况下
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径下是否有指定的资源
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean
@ConditionalOnWebApplication:当前项目是Web项目的条件下

2.5创建spring.factories

在 resources/META-INF/ 文件夹下创建spring.factories文件,内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.sp.autoconfigure.StarterAutoConfigure

右边的就是自动配置类的类路径,注意单词别打错了,我就是META-INF打成了MATA-INF害我折腾了半天。

三、测试

  1. 执行mvn install命令打包到本地
  2. 在另外一个项目添加依赖
<dependency>
<groupId>cn.sp</groupId>
<artifactId>example-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

然后可以看到jar包的结构图如下:

3. 在application.properties文件添加如下内容

cn.sp.enabled=true
cn.sp.config=fdafdf,ss1,DSDS,DDD
  1. 编写测试类并启动
@RunWith(SpringRunner.class)
@SpringBootTest
public class MySpringbootApplicationTests { @Autowired
StarterService starterService; @Test
public void contextLoads() {
String[] strings = starterService.split(",");
for (int i = 0; i < strings.length; i++) {
System.out.println(strings[i]);
}
} }
  1. 运行结果如下则表示成功。

2019-05-23 10:41:49.219 [main] INFO cn.sp.MySpringbootApplicationTests - Started MySpringbootApplicationTests in 10.977 seconds (JVM running for 13.035)
fdafdf
ss1
DSDS
DDD

2019-05-23 10:41:52.411 [Thread-4] INFO o.s.w.c.s.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@51f49060: startup date [Thu May 23 10:41:38 CST 2019]; root of context hierarchy

四、原理

1.在应用程序启动过程中,Spring Boot使用SpringFactoriesLoader类加载器查找org.springframework.boot.autoconfigure.EnableAutoConfiguration关键字对应的Java配置文件。Spring Boot会遍历在各个jar包中META-INF目录下的spring.factories文件,构建成一个配置文件链表。
2.根据spring.factories配置加载AutoConfigure类
3.根据 @Conditional注解的条件,进行自动配置并将Bean注入Spring Context中。
注意: Spring Boot的starter在编译时不需要依赖Spring Boot的库。
代码地址:https://github.com/2YSP/example-spring-boot-starter
参考:
https://juejin.im/entry/58d37630570c350058c2c15c
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html

【SpringBoot】编写一个自己的Starter的更多相关文章

  1. SpringBoot编写自定义的starter 专题

    What’s in a name All official starters follow a similar naming pattern; spring-boot-starter-*, where ...

  2. 编写一个可复用的SpringBoot应用运维脚本

    前提 作为Java开发者,很多场景下会使用SpringBoot开发Web应用,目前微服务主流SpringCloud全家桶也是基于SpringBoot搭建的.SpringBoot应用部署到服务器上,需要 ...

  3. JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

    JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...

  4. 从零开始开发一个Spring Boot Starter

    一.Spring Boot Starter简介 Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境( 条件 ...

  5. SpringBoot内置的各种Starter是怎样构建的?--SpringBoot源码(六)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五) 温 ...

  6. 基于SpringBoot开发一个Restful服务,实现增删改查功能

    前言 在去年的时候,在各种渠道中略微的了解了SpringBoot,在开发web项目的时候是如何的方便.快捷.但是当时并没有认真的去学习下,毕竟感觉自己在Struts和SpringMVC都用得不太熟练. ...

  7. 开发一个Spring Boot Starter!

    在上一篇文章中,我们已经了解了一个starter实现自动配置的基本流程,在这一小结我们将复现上一过程,实现一个自定义的starter. 先来分析starter的需求: 在项目中添加自定义的starte ...

  8. springboot搭建一个简单的websocket的实时推送应用

    说一下实用springboot搭建一个简单的websocket 的实时推送应用 websocket是什么 WebSocket是一种在单个TCP连接上进行全双工通信的协议 我们以前用的http协议只能单 ...

  9. 【SpingBoot】 测试如何使用SpringBoot搭建一个简单后台1

    很久没写博客了,最近接到一个组内的测试开发任务是做一个使用SpringBoot 开发一个后台程序(还未完成),特写感想记录一下 1. 为什么选择SpringBoot ? 首先是目前很多公司的后台还是J ...

随机推荐

  1. HAOI 2017 游记

    省选 2017年4月23日 流水账式游记,不喜勿喷. Day0: 准备出发,上午敲了一顿板子,板子敲完了就打小游戏,老师也不管了. 过程中各种奶,说什么今年一定考仙人掌啦,今年一定考字符串啦,今年一定 ...

  2. 通过崩溃trace来查找问题原因

    从友盟中, 我们可能会得到如下信息: Application received signal SIGSEGV (null) ( 0 CoreFoundation 0x359348a7 __except ...

  3. Sqooop- 使用Sqoop进行数据的导入导出

    Sqoop是Apache旗下的一个开源框架,专门用来做数据的导入和导出. 官网:https://sqoop.apache.org/ Sqoop的安装非常简单,只需要把下载下来的tar包解压设置两个环境 ...

  4. BZOJ 1640 [Usaco2007 Nov]Best Cow Line 队列变换:贪心【字典序最小】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1640 题意: 给你一个长度为n的字符串. 你可以将原串的首字母或尾字母移动到新串的末尾. ...

  5. redis持久化【转】

    Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集(diff ...

  6. db2move 数据导出整理

    db2move <database-name> <action> [<option>   <value>] 命令解释:1).database-name, ...

  7. 【HDU2050】折线分割平面

    Position Solution 2×n^2-n+1 证明见分割问题 Code // This file is made by YJinpeng,created by XuYike's black ...

  8. mvn使用记录

    1. mvn dependency:copy-dependencies 会导出到targed/dependency 下面 2. mvn dependency:copy-dependencies -Do ...

  9. Python: Neural Networks

    这是用Python实现的Neural Networks, 基于Python 2.7.9, numpy, matplotlib. 代码来源于斯坦福大学的课程: http://cs231n.github. ...

  10. CentOS 性能监控之nmon

    工具集: Nmon  性能数据收集分析工具Nmon analyser 性能数据分析工具,excel文件nmon_x86_sles10  Nmon在x86_sles10下二进制执行文件 nmon概述 n ...