一、什么是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. 解决/usr/bin/ld: cannot find -lmysqlclient错误

    类似/usr/bin/ld: cannot find -xxxx的错误有很多, 首先我们可以最简单的判断一下: 这类情况一般是由于缺乏某某库文件, 又或者可能是由于已存在的库问题版本不对造成的 一般都 ...

  2. 前端开发工程师必备JS技能-切图

    /******************************************** 学习时间:2015年12月21日 学习者:易天曦 学习目的:掌握切图技巧 学习目标:1.学会从网页设计师的P ...

  3. Django 之 Paginator 分页功能

    Django Paginator Django 分页官方文档  https://docs.djangoproject.com/en/1.10/topics/pagination/ 此分页方法没有限制显 ...

  4. python做简易记事本

    以下内容参考<辛星tkinter教程第二版>: from tkinter import * from tkinter.filedialog import * from tkinter.me ...

  5. Android sdk 搭建

    下载安装 http://pan.baidu.com/wap/share/home?uk=67915989&third=0 搭建Android环境时,无论使用的Eclipse还是Android ...

  6. Linux_学习_01_ 压缩文件夹

    二.参考资料 1.Linux下压缩某个文件夹命令

  7. POJ3693Maximum repetition substring (循环节)(后缀数组+RMQ)

    The repetition number of a string is defined as the maximum number R such that the string can be par ...

  8. inteliji ---idea 如何创建scala程序配置

    首先创建一个新的工程: #####################################################################################

  9. BZOJ_3124_[Sdoi2013]直径_树形DP

    BZOJ_3124_[Sdoi2013]直径_树形DP Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵 ...

  10. javacpp-FFmpeg系列补充:FFmpeg拉流截图实现在线演示demo(视频截图并返回base64图像,支持jpg/png/gif/bmp等多种格式)

    javacpp-ffmpeg系列: javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片 javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转 ...