Spring Boot Starters是什么?

版权声明:该文转自: http://www.nosuchfield.com/2017/10/15/Spring-Boot-Starters/。版权归原创做者,在此对原做者的付出表示感谢!html

  starter是SpringBoot中的一个新发明,它有效的下降了项目开发过程的复杂程度,对于简化开发操做有着很是好的效果。本文转载了一片文章,详细介绍了spring boot stater是什么?它的做用是什么?git

  Spring Boot Starter是在SpringBoot组件中被提出来的一种概念,stackoverflow上面已经有人归纳了这个starter是什么东西,想看完整的回答戳这里(https://stackoverflow.com/questions/28273543/what-are-spring-boot-starter-jars/28273660#28273660)github

  大概意思就是说starter是一种对依赖的synthesize(合成),这是什么意思呢?我能够举个例子来讲明。spring

    传统的作法

  在没有starter以前,假如我想要在Spring中使用jpa,那我可能须要作如下操做:数据库

  1. 在Maven中引入使用的数据库的依赖(即JDBC的jar)
  2. 引入jpa的依赖
  3. 在xxx.xml中配置一些属性信息
  4. 反复的调试直到能够正常运行

  须要注意的是,这里操做在咱们每次新建一个须要用到jpa的项目的时候都须要重复的作一次。也许你在第一次本身创建项目的时候是在Google上本身搜索了一番,花了半天时间解决掉了各类奇怪的问题以后,jpa终于能正常运行了。有些有经验的人会在OneNote上面把此次创建项目的过程给记录下来,包括操做的步骤以及须要用到的配置文件的内容,在下一次再建立jpa项目的时候,就不须要再次去Google了,只须要照着笔记来,以后再把全部的配置文件copy&paste就能够了。apache

  像上面这样的操做也不算不行,事实上咱们在没有starter以前都是这么干的,可是这样作有几个问题:app

  1. 若是过程比较繁琐,这样一步步操做会增长出错的可能性
  2. 不停地copy&paste不符合Don’t repeat yourself精神
  3. 在第一次配置的时候(尤为若是开发者比较小白),须要花费掉大量的时间

  使用Spring Boot Starter提高效率

  starter的主要目的就是为了解决上面的这些问题。maven

  starter的理念:starter会把全部用到的依赖都给包含进来,避免了开发者本身去引入依赖所带来的麻烦。须要注意的是不一样的starter是为了解决不一样的依赖,因此它们内部的实现可能会有很大的差别,例如jpa的starter和Redis的starter可能实现就不同,这是由于starter的本质在于synthesize,这是一层在逻辑层面的抽象,也许这种理念有点相似于Docker,由于它们都是在作一个“包装”的操做,若是你知道Docker是为了解决什么问题的,也许你能够用Docker和starter作一个类比。spring-boot

  starter的实现:虽然不一样的starter实现起来各有差别,可是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。由于Spring Boot坚信“约定大于配置”这一理念,因此咱们使用ConfigurationProperties来保存咱们的配置,而且这些配置均可以有一个默认值,即在咱们没有主动覆写原始配置的状况下,默认值就会生效,这在不少状况下是很是有用的。除此以外,starter的ConfigurationProperties还使得全部的配置属性被汇集到一个文件中(通常在resources目录下的application.properties),这样咱们就告别了Spring项目中XML地狱。ui

  starter的总体逻辑:

  上面的starter依赖的jar和咱们本身手动配置的时候依赖的jar并无什么不一样,因此咱们能够认为starter实际上是把这一些繁琐的配置操做交给了本身,而把简单交给了用户。除了帮助用户去除了繁琐的构建操做,在“约定大于配置”的理念下,ConfigurationProperties还帮助用户减小了无谓的配置操做。而且由于 application.properties 文件的存在,即便须要自定义配置,全部的配置也只须要在一个文件中进行,使用起来很是方便。

  了解了starter其实就是帮助用户简化了配置的操做以后,要理解starter和被配置了starter的组件之间并非竞争关系,而是辅助关系,即咱们能够给一个组件建立一个starter来让最终用户在使用这个组件的时候更加的简单方便。基于这种理念,咱们能够给任意一个现有的组件建立一个starter来让别人在使用这个组件的时候更加的简单方便,事实上Spring Boot团队已经帮助现有大部分的流行的组件建立好了它们的starter,你能够在这里查看这些starter的列表。

  建立本身的Spring Boot Starter

  若是你想要本身建立一个starter,那么基本上包含如下几步

  1. 建立一个starter项目,关于项目的命名你能够参考这里
  2. 建立一个ConfigurationProperties用于保存你的配置信息(若是你的项目不使用配置信息则能够跳过这一步,不过这种状况很是少见)
  3. 建立一个AutoConfiguration,引用定义好的配置信息;在AutoConfiguration中实现全部starter应该完成的操做,而且把这个类加入spring.factories配置文件中进行声明
  4. 打包项目,以后在一个SpringBoot项目中引入该项目依赖,而后就可使用该starter了

  咱们来看一个例子(例子的完整代码位于https://github.com/RitterHou/learn-spring-boot-starter

  首先新建一个Maven项目,设置 pom.xml 文件以下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6     <artifactId>http-starter</artifactId>
 7     <version>0.0.1-SNAPSHOT</version>
 8 
 9     <!-- 自定义starter都应该继承自该依赖 -->
10     <!-- 若是自定义starter自己须要继承其它的依赖,能够参考 https://stackoverflow.com/a/21318359 解决 -->
11     <parent>
12         <groupId>org.springframework.boot</groupId>
13         <artifactId>spring-boot-starters</artifactId>
14         <version>1.5.2.RELEASE</version>
15     </parent>
16 
17     <dependencies>
18         <!-- 自定义starter依赖此jar包 -->
19         <dependency>
20             <groupId>org.springframework.boot</groupId>
21             <artifactId>spring-boot-starter</artifactId>
22         </dependency>
23         <!-- lombok用于自动生成get、set方法 -->
24         <dependency>
25             <groupId>org.projectlombok</groupId>
26             <artifactId>lombok</artifactId>
27             <version>1.16.10</version>
28         </dependency>
29     </dependencies>
30 
31 </project>

  建立proterties类来保存配置信息:

 

1 @ConfigurationProperties(prefix = "http") // 自动获取配置文件中前缀为http的属性,把值传入对象参数
2 @Setter
3 @Getter
4 public class HttpProperties {
5 
6     // 若是配置文件中配置了http.url属性,则该默认属性会被覆盖
7     private String url = "http://www.baidu.com/";
8 
9 }

  上面这个类就是定义了一个属性,其默认值是 http://www.baidu.com/,咱们能够经过在 application.properties中添加配置 http.url=https://www.zhihu.com 来覆盖参数的值。

  建立业务类:

 

 1 @Setter
 2 @Getter
 3 public class HttpClient {
 4 
 5     private String url;
 6 
 7     // 根据url获取网页数据
 8     public String getHtml() {
 9         try {
10             URL url = new URL(this.url);
11             URLConnection urlConnection = url.openConnection();
12             BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "utf-8"));
13             String line = null;
14             StringBuilder sb = new StringBuilder();
15             while ((line = br.readLine()) != null) {
16                 sb.append(line).append("\n");
17             }
18             return sb.toString();
19         } catch (Exception e) {
20             e.printStackTrace();
21         }
22         return "error";
23     }
24 
25 }

  这个业务类的操做很是简单,只包含了一个 url 属性和一个 getHtml 方法,用于获取一个网页的HTML数据,读者看看就懂了。

  建立AutoConfiguration

 1 @Configuration
 2 @EnableConfigurationProperties(HttpProperties.class)
 3 public class HttpAutoConfiguration {
 4 
 5     @Resource
 6     private HttpProperties properties; // 使用配置
 7 
 8     // 在Spring上下文中建立一个对象
 9     @Bean
10     @ConditionalOnMissingBean
11     public HttpClient init() {
12         HttpClient client = new HttpClient();
13 
14         String url = properties.getUrl();
15         client.setUrl(url);
16         return client;
17     }
18 
19 }

  在上面的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,代码以下:

 1 @Component
 2 public class RunIt {
 3 
 4     @Resource
 5     private HttpClient httpClient;
 6 
 7     public void hello() {
 8         System.out.println(httpClient.getHtml());
 9     }
10 
11 }

  正常状况下此方法的执行会打印出url http://www.baidu.com/ 的HTML内容,以后咱们在application.properties中加入配置:

http.url=https://www.zhihu.com/

  再次运行程序,此时打印的结果应该是知乎首页的HTML了,证实properties中的数据确实被覆盖了。

相关文章
相关标签/搜索