Spring Boot Starter 是在 SpringBoot 组件中被提出来的一种概念,stackoverflow 上面已经有人归纳了这个 starter 是什么东西,想看完整的回答戳 这里。html
Starter POMs are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, just include the spring-boot-starter-data-jpa dependency in your project, and you are good to go.git
大概意思就是说 starter 是一种对依赖的 synthesize(合成),这是什么意思呢?我能够举个例子来讲明。github
在没有 starter 以前,假如我想要在 Spring 中使用 jpa,那我可能须要作如下操做:web
须要注意的是,这里操做在咱们 每次新建一个须要用到 jpa 的项目的时候都须要重复的作一次。也许你在第一次本身创建项目的时候是在 Google 上本身搜索了一番,花了半天时间解决掉了各类奇怪的问题以后,jpa 终于能正常运行了。有些有经验的人会在 OneNote 上面把此次创建项目的过程给记录下来,包括操做的步骤以及须要用到的配置文件的内容,在下一次再建立 jpa 项目的时候,就不须要再次去 Google 了,只须要照着笔记来,以后再把全部的配置文件 copy&paste 就能够了。spring
像上面这样的操做也不算不行,事实上咱们在没有 starter 以前都是这么干的,可是这样作有几个问题:数据库
starter 的主要目的就是为了解决上面的这些问题。apache
starter 的理念:starter 会把全部用到的依赖都给包含进来,避免了开发者本身去引入依赖所带来的麻烦。须要注意的是不一样的 starter 是为了解决不一样的依赖,因此它们内部的实现可能会有很大的差别,例如 jpa 的 starter 和 Redis 的 starter 可能实现就不同,这是由于 starter 的本质在于 synthesize,这是一层在逻辑层面的抽象,也许这种理念有点相似于 Docker,由于它们都是在作一个 “包装” 的操做,若是你知道 Docker 是为了解决什么问题的,也许你能够用 Docker 和 starter 作一个类比。app
starter 的实现:虽然不一样的 starter 实现起来各有差别,可是他们基本上都会使用到两个相同的内容:ConfigurationProperties 和 AutoConfiguration。由于 Spring Boot 坚信 “约定大于配置” 这一理念,因此咱们使用 ConfigurationProperties 来保存咱们的配置,而且这些配置均可以有一个默认值,即在咱们没有主动覆写原始配置的状况下,默认值就会生效,这在不少状况下是很是有用的。除此以外,starter 的 ConfigurationProperties 还使得全部的配置属性被汇集到一个文件中(通常在 resources 目录下的 application.properties),这样咱们就告别了 Spring 项目中 XML 地狱。maven
starter 的总体逻辑: 编辑器
上面的 starter 依赖的 jar 和咱们本身手动配置的时候依赖的 jar 并无什么不一样,因此咱们能够认为 starter 实际上是把这一些繁琐的配置操做交给了本身,而把简单交给了用户。除了帮助用户去除了繁琐的构建操做,在 “约定大于配置” 的理念下,ConfigurationProperties 还帮助用户减小了无谓的配置操做。而且由于 application.properties
文件的存在,即便须要自定义配置,全部的配置也只须要在一个文件中进行,使用起来很是方便。
了解了 starter 其实就是帮助用户简化了配置的操做以后,要理解 starter 和被配置了 starter 的组件之间并非竞争关系,而是辅助关系,即咱们能够给一个组件建立一个 starter 来让最终用户在使用这个组件的时候更加的简单方便。基于这种理念,咱们能够给任意一个现有的组件建立一个 starter 来让别人在使用这个组件的时候更加的简单方便,事实上 Spring Boot 团队已经帮助现有大部分的流行的组件建立好了它们的 starter,你能够在这里查看这些 starter 的列表。
若是你想要本身建立一个 starter,那么基本上包含如下几步
咱们来看一个例子(例子的完整代码位于 https://github.com/RitterHou/learn-spring-boot-starter)
首先新建一个 Maven 项目,设置 pom.xml
文件以下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>http-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 自定义starter都应该继承自该依赖 -->
<!-- 若是自定义starter自己须要继承其它的依赖,能够参考 https://stackoverflow.com/a/21318359 解决 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<!-- 自定义starter依赖此jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- lombok用于自动生成get、set方法 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
</project>
建立 proterties 类来保存配置信息:
@ConfigurationProperties(prefix = "http") // 自动获取配置文件中前缀为http的属性,把值传入对象参数
@Setter
@Getter
public class HttpProperties {
// 若是配置文件中配置了http.url属性,则该默认属性会被覆盖
private String url = "http://www.baidu.com/";
}
上面这个类就是定义了一个属性,其默认值是 http://www.baidu.com/
,咱们能够经过在 application.properties
中添加配置 http.url=https://www.zhihu.com
来覆盖参数的值。
建立业务类:
@Setter
@Getter
public class HttpClient {
private String url;
// 根据url获取网页数据
public String getHtml() {
try {
URL url = new URL(this.url);
URLConnection urlConnection = url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
}
这个业务类的操做很是简单,只包含了一个 url
属性和一个 getHtml
方法,用于获取一个网页的 HTML 数据,读者看看就懂了。
建立 AutoConfiguration
@Configuration
@EnableConfigurationProperties(HttpProperties.class)
public class HttpAutoConfiguration {
@Resource
private HttpProperties properties; // 使用配置
// 在Spring上下文中建立一个对象
@Bean
@ConditionalOnMissingBean
public HttpClient init() {
HttpClient client = new HttpClient();
String url = properties.getUrl();
client.setUrl(url);
return client;
}
}
在上面的 AutoConfiguration 中咱们实现了本身要求:在 Spring 的上下文中建立了一个 HttpClient 类的 bean,而且咱们把 properties 中的一个参数赋给了该 bean。 关于 @ConditionalOnMissingBean
这个注解,它的意思是在该 bean 不存在的状况下此方法才会执行,这个至关于开关的角色,更多关于开关系列的注解能够参考这里。
最后,咱们在 resources
文件夹下新建目录 META-INF
,在目录中新建 spring.factories
文件,而且在 spring.factories
中配置 AutoConfiguration:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.nosuchfield.httpstarter.HttpAutoConfiguration
到此,咱们的 starter 已经建立完毕了,使用 Maven 打包该项目。以后建立一个 SpringBoot 项目,在项目中添加咱们以前打包的 starter 做为依赖,而后使用 SringBoot 来运行咱们的 starter,代码以下:
@Component
public class RunIt {
@Resource
private HttpClient httpClient;
public void hello() {
System.out.println(httpClient.getHtml());
}
}
正常状况下此方法的执行会打印出 url http://www.baidu.com/
的 HTML 内容,以后咱们在 application.properties 中加入配置:
http.url=https://www.zhihu.com/
再次运行程序,此时打印的结果应该是知乎首页的 HTML 了,证实 properties 中的数据确实被覆盖了。
本文转载自:御坂研究所
原文连接:https://www.nosuchfield.com/2017/10/15/Spring-Boot-Starters/