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-autoconfigure
,starter
模块就叫做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