前言

我们都知道可以使用SpringBoot快速的开发基于Spring框架的项目。由于围绕SpringBoot存在很多开箱即用的Starter依赖,使得我们在开发业务代码时能够非常方便的、不需要过多关注框架的配置,而只需要关注业务即可。

例如我想要在SpringBoot项目中集成Redis,那么我只需要加入spring-data-redis-starter的依赖,并简单配置一下连接信息以及Jedis连接池配置就可以。这为我们省去了之前很多的配置操作。甚至有些功能的开启只需要在启动类或配置类上增加一个注解即可完成。

那么如果我们想要自己实现自己的Starter需要做些什么呢?下面就开始介绍如何实现自己的SpringBoot-xxx-starter。

原理

首先说说原理,我们知道使用一个公用的starter的时候,只需要将相应的依赖添加的Maven的配置文件当中即可,免去了自己需要引用很多依赖类,并且SpringBoot会自动进行类的自动配置。那么 SpringBoot 是如何知道要实例化哪些类,并进行自动配置的呢? 下面简单说一下。

首先,SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包,这类似于 Java 的 SPI 机制。

第二步,根据 spring.factories 配置加载AutoConfigure类。

最后,根据 @Conditional 注解的条件,进行自动配置并将Bean注入Spring Context 上下文当中。

我们也可以使用@ImportAutoConfiguration({MyServiceAutoConfiguration.class}) 指定自动配置哪些类。

实现

终于到了代码实现的步骤,接下来就开始编码我们自己的SpringBoot-starter。

第一步创建一个SpringBoot 项目,并添加下面两个依赖到pom.xml文件当中

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>

其中 spring-boot-configuration-processor 的作用是编译时生成 spring-configuration-metadata.json ,此文件主要给IDE使用。如当配置此jar相关配置属性在 application.yml ,你可以用ctlr+鼠标左键点击属性名,IDE会跳转到你配置此属性的类中。

我们日常使用的Spring官方的Starter一般采取spring-boot-starter-{name} 的命名方式,如 spring-boot-starter-web 

而非官方的Starter,官方建议 artifactId 命名应遵循{name}-spring-boot-starter 的格式。 例如:ysc-spring-boot-starter 

<groupId>com.ysc</groupId>
<artifactId>simple-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

第二步编写我们的Service类

这里讲一下我们的Starter要实现的功能,很简单,提供一个Service,包含一个能够将配置文件中配置的字符串根据传入的字符进行分割的方法String[] split(String separatorChar)

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

第三步编写配置文件读取类

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

第四步,编写AutoConfigure类 ,这步是关键点

@Configuration
@ConditionalOnClass(StarterService.class)
@EnableConfigurationProperties(StarterServiceProperties.class)
public class StarterAutoConfigure { @Autowired
private StarterServiceProperties properties; @Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "example.service", value = "enabled", havingValue = "true")
StarterService starterService (){
return new StarterService(properties.getConfig());
} }

解释一下代码中用到的几个注解:

  • @ConditionalOnClass,当classpath下发现该类的情况下进行自动配置。
  • @ConditionalOnMissingBean,当Spring Context中不存在该Bean时。
  • @ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true"),当配置文件中example.service.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项目的条件下

最后一步,在resources/META-INF/下创建spring.factories文件,并添加如下内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.autocinfigure.StarterAutoConfigure

至此,我们的一个Starter代码部分就是完成了,下面将项目安装到本地Maven仓库中。

发布

在项目根目录执行 mvn install 进行打包安装。

测试

将Starter项目的依赖添加到我们自己的SpringBoot项目中

<dependency>
<groupId>com.ysc</groupId>
<artifactId>simple-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

application.yml 配置文件中添加配置信息:

example
service
enabled: true
config: abc-des-dde,SSS-DRS-RE,SDR-SDFR-XXX

在本地使用JUnit进行代码测试

@Autowired
private StarterService starterService; @Test
public void starterTest() {
String[] splitArray = starterService.split(",");
System.out.println(splitArray);
}

好,到这我们的一个自定义Stater就完成了

编写自己的SpringBoot-starter的更多相关文章

  1. Springboot 系列(十五)如何编写自己的 Springboot starter

    1. 前言 Springboot 中的自动配置确实方便,减少了我们开发上的复杂性,那么自动配置原理是什么呢?之前我也写过了一篇文章进行了分析. Springboot 系列(三)Spring Boot ...

  2. SpringBoot Starter缘起

    SpringBoot通过SpringBoot Starter零配置自动加载第三方模块,只需要引入模块的jar包不需要任何配置就可以启用模块,遵循约定大于配置的思想. 那么如何编写一个SpringBoo ...

  3. 小D课堂 - 零基础入门SpringBoot2.X到实战_第7节 SpringBoot常用Starter介绍和整合模板引擎Freemaker、thymeleaf_28..SpringBoot Starter讲解

    笔记 1.SpringBoot Starter讲解     简介:介绍什么是SpringBoot Starter和主要作用 1.官网地址:https://docs.spring.io/spring-b ...

  4. SpringBoot Starter机制 - 自定义Starter

    目录 前言 1.起源 2.SpringBoot Starter 原理 3.自定义 Starter 3.1 创建 Starter 3.2 测试自定义 Starter 前言         最近在学习Sp ...

  5. 自定义springboot - starter 实现日志打印,并支持动态可插拔

    1. starter 命名规则: springboot项目有很多专一功能的starter组件,命名都是spring-boot-starter-xx,如spring-boot-starter-loggi ...

  6. 从头带你撸一个Springboot Starter

    我们知道 SpringBoot 提供了很多的 Starter 用于引用各种封装好的功能: 名称 功能 spring-boot-starter-web 支持 Web 开发,包括 Tomcat 和 spr ...

  7. SpringBoot starter 作用在什么地方?

    依赖管理是所有项目中至关重要的一部分.当一个项目变得相当复杂,管理依赖会成为一个噩梦,因为当中涉及太多 artifacts 了. 这时候 SpringBoot starter 就派上用处了.每一个 s ...

  8. 【SpringBoot】编写一个自己的Starter

    一.什么是Starter? 在开发过程中我们就经常使用到各种starter,比如mybatis-spring-boot-starter,只需要进行简单的配置即可使用,就像一个插件非常方便.这也是Spr ...

  9. 手写一个springboot starter

    springboot的starter的作用就是自动装配.将配置类自动装配好放入ioc容器里.作为一个组件,提供给springboot的程序使用. 今天手写一个starter.功能很简单,调用start ...

  10. OpenFeign封装为springboot starter

    OpenFeign是什么 随着业务的增多,我们的单体应用越来越复杂,单机已经难以满足性能的需求,这时候出现了分布式.分布式通讯除了RPC, REST HTTP请求是最简单的一种方式.OpenFeign ...

随机推荐

  1. 【转】require.js学习笔记(一)

    一.立即执行函数 立即执行函数可以有效避免临时变量污染全局空间.可以在页面初始化时,在立即执行函数内实现一次执行变量的定义及使用. for (var i = 0; i < elems.lengt ...

  2. (记忆化搜索)数塔 (zznu 1271)

    http://acm.zznu.edu.cn/problem.php?id=1271 1271: 数塔 时间限制: 1 Sec  内存限制: 128 MB提交: 109  解决: 78[提交][状态] ...

  3. 从kepware定时取web api内容

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  4. html5+javascript的管廊监控页面

    这周二做的,支持苹果手机,安卓手机,电脑,平板访问

  5. js跳转页面方法实现汇总

    一.页面之间的跳转传参 1.在页面之间跳转的方式有两种: window.location.href=”test.html?num=10”   地址会改变参数也会被传递但是不会打开新窗口 window. ...

  6. iOS 5 故事板进阶(1)

    译自<iOS 5 by tutorials> 在上一章,你已经学习了故事板的基本用法.包括如何向故事板中添加 View Controller,通过 segues 切换 View Contr ...

  7. AngularJS $observe $watch

    $observe $watch都可以用来监听值的变化,但是他们有显著的区别.$observe是用来监视DOM属性值的变化,而 $watch监视scope属性值的变化.AngularJS中的监听,都知道 ...

  8. Android-Java-死锁

    死锁:程序不往下执行了,程序又没有结束,就一直卡在哪里: 在使用synchronized的时候要避免死锁,synchronized嵌套就可能会引发死锁,需要严格的检查代码,排除死锁发生的可能: 特意演 ...

  9. 《AngularJS深度剖析与最佳实践》笔记: 第二章 概念介绍

    第二章 概念介绍 2.1 什么是UI? 用户界面包括内容(静态信息+动态信息), 外观, 交互. 在前端技术栈中分别由HTML, CSS和JS负责. 进一步抽象, 分别对应于MVC三个主要部分: Mo ...

  10. 【BZOJ3193】 [JLOI2013]地形生成

    BZOJ3193 [JLOI2013]地形生成 Solution 第一问不是很简单吗? 直接计数就好了. 第二问思考无果看了看hyj神仙的代码,发现可以dp求解. 具体可以看代码(其实主要是我说不清楚 ...