创建属于自己的Spring Boot Starter

1、前言

最近公司在做一个中台项目,涉及到公司内部系统调用,考虑到每上马一个项目都需要进行客户端接口开发。本着对公司对项目对个人负责的态度,为防止各项目重复性开发,且项目组因个人能力问题,为降低代码耦合,强烈要求本次中台项目对于公司内各系统开发各自的SDK,创建属于各自的Spring Boot Starter

另外,我还有一个要求就是需要支持Apollo配置中心,下面看看我们是怎么操作的吧!文末有源码地址哦!

2、项目结构

一个完整的Spring Boot Starter可能包含了下面两个模块

  • autoconfigure 模块包含了 auto-configuration 相关代码.
  • starter模块依赖autoconfigure模块,且包含了其他通用的依赖项 ,简单来说就是它包含了使用该starter的一切。

注意:这两个模块不是必须的,可以合并成一个模块,实际项目中我们就是采用合并的方式,但是本文还是按照两个来介绍

下面看下我准备的案例的结构:

fucking-great/
├── fg-spring-boot-autoconfigure
├── fg-spring-boot-sample
└── fg-spring-boot-starter

这里我们多新建了一个模块叫fg-spring-boot-sample主要是为了模仿实际项目依赖使用本次新建的starter而专门设计的单元测试模块

3、命名规范

不要以spring-boot开头来命名自定义的starter,官方支持的会使用此开头来命名。假设你创建一个项目叫“FuckingGreat”(牛逼),我还没开始干,看到名字就感觉起飞了。兴奋的感觉自己要干一票大事情,感觉走上了人生巅峰。咳咳.....回到正轨,你可以定义autoconfigure模块叫fg-spring-boot-autoconfigurestarter模块就叫做fg-spring-boot-starter

4、autoconfigure模块

autoconfigure包含了启动库的一切依赖,它可能包含了参数配置的关键定义(例:@ConfigurationProperties)和任何回调接口,以便未来可以自定义启动方式。

我们建议在autoconfigure模块添加如下依赖

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

它可以帮助我们在编译打包starter后自动生成元数据在META-INF/spring-autoconfigure-metadata.properties目录下,另外注意使用了标签<optional>true</optional>用以帮助提升启动时间

如果我们想要创建额外的自定义的元数据,我们可以添加如下依赖,当然我们这里是要加的,经过测试发现不加此依赖的话,在sample模块的application.propeties输入具体配置的时候IDE无法自动提示。

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

参考文档: Generating Your Own Metadata

我们看一下本次介绍案例该模块下有哪些代码

├── autoconfigure
│   ├── FuckingGreatAutoConfiguration.java
│   └── FuckingGreatProperties.java
└── service
    └── FuckingGreatService.java

4.1、FuckingGreatProperties 类

它就是一个properties配置文件,用于接收自定义的属性

package com.example.fg.autoconfigure;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author cattle -  稻草鸟人
 * @date 2020/3/14 下午6:40
 */
@Data
@ConfigurationProperties(prefix = "com.example.fg")
public class FuckingGreatProperties {

    /**
     * input your name
     */
    private String name;


}

4.2、FuckingGreatService 类

它是本案例starter提供具体服务的类,我们看下代码

package com.example.fg.service;

import com.example.fg.autoconfigure.FuckingGreatProperties;
import lombok.AllArgsConstructor;

/**
 * @author cattle -  稻草鸟人
 * @date 2020/3/14 下午6:47
 */
@AllArgsConstructor
public class FuckingGreatService {

    FuckingGreatProperties fuckingGreatProperties;

    public String hello() {
        return fuckingGreatProperties.getName();
    }

}

4.3、FuckingGreatAutoConfiguration 类

它为我们初始化了一个服务bean

package com.example.fg.autoconfigure;

import com.example.fg.service.FuckingGreatService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

/**
 * @author cattle -  稻草鸟人
 * @date 2020/3/14 下午6:24
 */
@EnableConfigurationProperties(FuckingGreatProperties.class)
public class FuckingGreatAutoConfiguration {


    @Bean
    @ConditionalOnMissingBean
    public FuckingGreatService fuckingGreatService(FuckingGreatProperties fuckingGreatProperties) {
        return new FuckingGreatService(fuckingGreatProperties);
    }
}

4.4、spring.factories

在resources目录下,我们需要新建一个目录叫META-INF的文件夹,然后在META-INF目录下新建spring.factories文件,该文件内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.fg.autoconfigure.FuckingGreatAutoConfiguration

5、starter模块

它就是个空模块,它的唯一目的是提供使用库所必需的依赖项,本次案例它就依赖了autoconfigure模块而已

6、sample模块

首先我们创建了一个applicaiton.properties文件,内容如下:

com.example.fg.name=cattle

然后我们写的一个单元测试类:

package com.example.fg;

import com.example.fg.service.FuckingGreatService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;


@SpringBootTest
class FuckingGreatApplicationTest {

    @Autowired
    FuckingGreatService fuckingGreatService;

    @Test
    public void test() {
        String name = fuckingGreatService.hello();
        assertEquals(name, "cattle");
    }
}

7、Ctrip Apollo集成测试

这个也很简单啦,搭建好Apollo之后,修改sample模块下test/resources目录下的aplicaiton.properties文件内容如下:

#com.example.fg.name=cattle

app.id=100004458
apollo.autoUpdateInjectedSpringProperties=false
# Apollo Meta Server 地址
apollo.meta=http://xx.xx.xx.xx:8080
# 自定义本地配置文件缓存路径
apollo.cacheDir=./cache
# 设置在应用启动阶段就加载 Apollo 配置
apollo.bootstrap.enabled=true
# 注入 application namespace
apollo.bootstrap.namespaces=application

然后在项目启动类上面增加注解@EnableApolloConfig即可

8、源码地址

https://github.com/cattles/fucking-great-autoconfigure.git

9、参考文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容