前言
对于正在构建的Spring Boot应用程序,我们不希望每次都从0开始实现某些特定功能。相反,我们希望仅实现功能一次,并根据需要将该功能包含在任何应用中。一次实现,处处引用。
在Spring Boot中,启动器就是完成这种任务的利器。启动器可以轻松的包含一组特定功能,并能轻松的使用它们。
使用Spring Boot启动器的场景:
- 提供可配置和/或默认的日志配置,或使日志轻易的记录到中心日志服务器。
- 提供可配置和/或安全配置。
- 提供可配置和/或默认的错误处理策略。
- 为消息中间件提供适配器。
- 集成第三方库并使其可配置为与Spring Boot一起使用
在本文中,我们将构建一个Spring Boot启动器,它允许Spring Boot应用程序使用华为云提供的OBS服务存储和读取数据。
样例代码
样例代码可以obs-starter获取。
Spring Boot启动器基本概念
在深入了解创建Spring Boot启动器的细节之前,让我们讨论有助于理解启动器工作原理的基本概念。
什么是应用上下文?
在一个Spring应用中,应用上下文是组成应用对象(beans)的网络。应用上下文包含web controller,service,repository和一切应用运行需要的对象,这些对象通常都是无状态的。
什么是 Spring 配置?
使用@Configuration
注解的类充当添加到应用程序上下文bean的工厂。可能包含多个工厂方法(@Bean
),方法的返回值会被Spring自动添加到应用上下文中。
简而言之,Spring Configuration为应用上下文提供beans。
什么是自动配置?
自动配置是一个可以被Spring自动发现的配置类(使用@Configuration
注解)。只要在类路径上找到自动配置,Spring就会对其进行计算,并将配置的贡献(比如,创建Bean)添加到应用程序上下文中。自动配置可以是有条件的,自动配置生效可以依赖外部因素,比如具有特定值的配置(一切皆是受控的)。
什么是自动配置模块?
自动配置模块是包含自动配置类的Maven或Gradle模块。这样,我们就可以构建自动为应用程序上下文做贡献的模块,添加某个功能或提供对某个外部库的访问。我们在Spring Boot应用程序中使用它所要做的唯一工作就是在pom.xml
或build.gradle
中包含一个依赖项。
Spring Boot团队大量使用此方法将Spring Boot与外部库集成。
什么是 Spring Boot 启动器?
Spring Boot Starter是一个Maven或Gradle模块,其唯一目的是提供“使用特定功能”的所有依赖项。这通常意味着它是一个单独的pom.xml
或build.gradle
文件,它包含一个或多个自动配置模块的依赖项以及可能需要的任何其他依赖项。在Spring Boot应用中,使用这些功能只需要包含这个启动器即可(添加一个依赖)。
为OBS服务构建一个启动器
下面以一个具体例子讨论如何实现一个启动器。想象一下我们在微服务环境中工作,所有的微服务都需要从OBS服务存储数据或查询数据,我们希望通过一个启动器来实现该功能并被所有微服务共享。OBS启动器会提供以下功能:
- 一个
ObsWriter
bean允许微服务向OBS写数据。 - 一个
ObsReader
bean允许微服务从OBS读数据。
支持OBS信息可配置
连接华为云OBS服务需要使用AK、SK和Endpoint三个信息,为了支持不同微服务对接不同的OBS服务(不同租户的OBS,不同region的OBS),AK、SK和Endpoint需要支持配置:
@ConfigurationProperties(prefix = "obs.info")
@Configuration
public class ObsInfoProperties {
@Value(value = "${ak:default ak}")
private String ak;
@Value(value = "${sk:default sk}")
private String sk;
@Value(value = "${endPoint:https://obs.cn-north-5.myhuaweicloud.com}")
private String endPoint;
// getter,setter方法
}
微服务可以通过 application.properties
或application.yaml
配置需要使用的OBS服务信息:
application.properties
的文件内容如下:
obs.info.ak = your self ak
obs.info.sk =your self sk
obs.info.endPoint = the endpoint you want to connect
application.yaml
的文件内容如下:
obs:
info:
ak: your self ak
sk: your self sk
enPoint: your self endpoint
提供一个自动配置
作为启动器功能的切入点,我们首先提供一个@Configuration
class:
@Configuration
@EnableConfigurationProperties(ObsInfoProperties.class)
public class ObsAutoConfiguration {
@Autowired
private ObsInfoProperties obsProperties;
@Bean
public ObsWriter obsWriter() {
String ak = obsProperties.getAk();
Assert.notNull(ak, "ak must not be null");
String sk = obsProperties.getSk();
Assert.notNull(sk, "sk must not be null");
String endPoint = obsProperties.getEndPoint();
Assert.notNull(endPoint, "endPoint must not be null");
return new ObsWriter(ak, sk, endPoint);
}
@Bean
public ObsReader obsReader() {
String ak = obsProperties.getAk();
Assert.notNull(ak, "ak must not be null");
String sk = obsProperties.getSk();
Assert.notNull(sk, "sk must not be null");
String endPoint = obsProperties.getEndPoint();
Assert.notNull(endPoint, "endPoint must not be null");
return new ObsReader(ak, sk, endPoint);
}
}
这个配置类包含了OBS功能需要的所有类,ObsWriter
和 ObsReader
两个Bean依赖 ObsInfoProperties
。为了使配置类成为一个自动配置类,需要在src/main/resource/META-INFO
目录下添加 spring.factories
文件,文件的内容为:
# 键值对的值为自动配置类的全限定名
org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.github.ctlove0523.obsstart.ObsAutoConfiguration
ObsWriter
和 ObsReader
的完整定义可以从Github获取:
ObsWriter
只包含属性的定义如下:
public class ObsWriter {
private ObsClient obsClient;
private String ak;
private String sk;
private String endPoint;
}
ObsReader
只包含属性的定义如下:
public class ObsReader {
private ObsClient obsClient;
private String ak;
private String sk;
private String endPoint;
}
让OBS功能成为可选功能
在任何时候允许关闭Spring Boot启动器的某些功能都是非常不错的想法。尤其是涉及对接外部系统时,比如对接华为云的存储服务OBS等。在研发内部环境或者研发测试环境,第三方的服务可能都无法使用,在这种情况下,关闭该功能是更好的选择。
在Spring Boot中有很多方法可以让一个 Bean
成为可选的 Bean
,在这里只是选取最简单的注解方式说明如何让一个Bean成为可选Bean,也就是如何关闭OBS功能,修改后的ObsAutoConfiguration
如下:
@Configuration
@EnableConfigurationProperties(ObsInfoProperties.class)
@ConditionalOnProperty(value = "obs.enabled", havingValue = "true")
public class ObsAutoConfiguration {
@Autowired
private ObsInfoProperties obsProperties;
@Bean
public ObsWriter obsWriter() {
// 不详细展示代码细节
return new ObsWriter(ak, sk, endPoint);
}
@Bean
public ObsReader obsReader() {
// 不详细展示代码细节
return new ObsReader(ak, sk, endPoint);
}
}
EnableConfigurationProperties
告诉Spring Boot,当且仅当obs.enabled
的值为true
时才创建并加载Bean
。
使用OBS启动器
现在OBS启动器已经开发完成,新构建或正在构建的Spring Boot应用只要包含OBS启动器,就可以使用OBS的功能,如果Spring Boot应用是基于Maven构建,只需要增加如下依赖项目即可开箱即用:
io.github.ctlove0523
obs-spring-boot-starter
0.0.3-SNAPSHOT
客户端可以在自己的配置文件中对AK,SK,Endpoint,是否开启OBS功能等进行配置:
application.properties
:
obs.info.ak = client use ak
obs.info.sk = client use sk
obs.info.endPoint = client want to connect endpoint
# 开启OBS功能
obs.enabled = true
参考文章
- Creating Your Own Starter
- Quick Guide to Building a Spring Boot Starter
- 华为OBS