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,那我可能须要作如下操做:spring
须要注意的是,这里操做在咱们每次新建一个须要用到jpa的项目的时候都须要重复的作一次。也许你在第一次本身创建项目的时候是在Google上本身搜索了一番,花了半天时间解决掉了各类奇怪的问题以后,jpa终于能正常运行了。有些有经验的人会在OneNote上面把此次创建项目的过程给记录下来,包括操做的步骤以及须要用到的配置文件的内容,在下一次再建立jpa项目的时候,就不须要再次去Google了,只须要照着笔记来,以后再把全部的配置文件copy&paste就能够了。数据库
像上面这样的操做也不算不行,事实上咱们在没有starter以前都是这么干的,可是这样作有几个问题:apache
starter的主要目的就是为了解决上面的这些问题。app
starter的理念:starter会把全部用到的依赖都给包含进来,避免了开发者本身去引入依赖所带来的麻烦。须要注意的是不一样的starter是为了解决不一样的依赖,因此它们内部的实现可能会有很大的差别,例如jpa的starter和Redis的starter可能实现就不同,这是由于starter的本质在于synthesize,这是一层在逻辑层面的抽象,也许这种理念有点相似于Docker,由于它们都是在作一个“包装”的操做,若是你知道Docker是为了解决什么问题的,也许你能够用Docker和starter作一个类比。maven
starter的实现:虽然不一样的starter实现起来各有差别,可是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。由于Spring Boot坚信“约定大于配置”这一理念,因此咱们使用ConfigurationProperties来保存咱们的配置,而且这些配置均可以有一个默认值,即在咱们没有主动覆写原始配置的状况下,默认值就会生效,这在不少状况下是很是有用的。除此以外,starter的ConfigurationProperties还使得全部的配置属性被汇集到一个文件中(通常在resources目录下的application.properties),这样咱们就告别了Spring项目中XML地狱。spring-boot
starter的总体逻辑:
ui
上面的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中的数据确实被覆盖了。