Java9新特性系列(module&maven&starter)

史培培發表於2018-02-11

Java9新特性系列(module&maven&starter)
上篇已經深入分析了Java9中的模組化,有讀者又提到了module與starter是什麼關係?本篇將進行分析。

首先先回顧下module與maven/gradle的關係:

module與maven/gradle是什麼關係?

模組化的依賴關係,很容易讓人聯想到mven和gradle,這個在上篇中也提及,後來有讀者也提出module和maven是什麼關係?解答如下:

Maven 有兩個主要的特徵:依賴管理和構建管理。 依賴管理即可以決定庫中的版本並從倉庫中下載下來。 構建管理即管理開發過程中的任務,包括初始化、編譯、測試、打包等。

Module是系統內建用於表述元件之間的關係,對於版本的管理還是處於最原始的狀體,管理一種強制的依賴關係。

總結一下:Maven還是主要負責構建管理,Modules 對於像Maven這樣的構建工具(build tools)來說扮演的是輔助補充的角色。因為這些構建工具在構建時建立的依賴關係圖譜和他們版本可以根據Module來建立,Module強制確定了module和artifacts之間的依賴關係,而Maven對於依賴並非是強制的。 具體可參考StackOverflow上的一篇問答:Project Jigsaw vs Maven on StackOverflow

說到starter,如果用過SpringBoot的開發者可能很熟悉,Starter主要用來簡化依賴用的。

Starter是什麼?

Starter主要用來簡化依賴用的

  • Starter前時代

在Starter之前做MVC時要引入日誌元件,比如log4j,那麼需要找到依賴的log4j的版本,有的時候版本不匹配也會出現問題,因為我們也不知道依賴什麼版本,那麼Starter就應運而生。

  • Starter

我們要在SpringBoot中引入WebMVC的支援時,我們只需引入這個模組spring-boot-starter-web,有了Starter之後,log4j就自動引入了,也不用關心版本這些問題,將這個模組如果解壓包出來會發現裡面什麼都沒有,只定義了一些POM依賴,所以說Starter的作用主要是簡化依賴。

  • SpringBoot Starters

《Spring Boot in Action》的附錄B列出了SpringBoot Starters的內容:

Starter(Group ID: org.springframework.boot) 傳遞依賴
spring-boot-starter-web org.springframework.boot:spring-boot-starter
org.springframework.boot:spring-boot-starter-tomcat
org.springframework.boot:spring-boot-starter-validation
com.fasterxml.jackson.core:jackson-databind
org.springframework:spring-web
org.springframework:spring-webmvc
spring-boot-starter-log4j2 org.apache.logging.log4j:log4j-slf4j-impl
org.apache.logging.log4j:log4j-api
org.apache.logging.log4j:log4j-core
org.slf4j:jcl-over-slf4j
org.slf4j:jul-to-slf4j
... ....

如何定義自己的Starter?

  • 基於已有starter進行擴充套件(pom.xml)
<!-- 依賴管理 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.5.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<!-- 新增依賴 -->
<dependencies>
    <!-- 自動配置依賴 -->
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-autoconfigure</artifactId> 
        <version>1.5.2.RELEASE</version>  
    </dependency>  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-configuration-processor</artifactId>  
        <version>1.5.2.RELEASE</version>  
        <optional>true</optional>  
    </dependency> 
</dependencies>
複製程式碼
  • 定義自動配置配置類
package net.hellomypastor.springboot.starter;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix="dog.proterties")
public class DogProperties {
    private String name;
    private int age;
    //set、get
}
複製程式碼
package net.hellomypastor.springboot.starter;

public class DogService {
    private DogProperties dogProperties;

    public DogService() {

    }

    public DogService(DogProperties dogProperties) {
        this.dogProperties = dogProperties;
    }

    public String getDogName() {
        return dogProperties.getName();
    }

    public int getDogAge() {
        return dogProperties.getAge();
    }
}
複製程式碼
package net.hellomypastor.springboot.starter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(DogProperties.class)
@ConditionalOnClass(DogService.class)
@ConditionalOnProperty(prefix="dog.proterties", value="enabled", matchIfMissing=true)
public class DogAutoConfiguration {
    @Autowired
    private DogProperties dogProperties;

    @Bean
    @ConditionalOnMissingBean(DogService.class)
    public DogService personService() {
        DogService dogService = new DogService(dogProperties);
        return dogService;
    }
}

複製程式碼
  • 修改META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=net.hellomypastor.configure.DogAutoConfiguration
複製程式碼
  • 打包

spring官方說明定義starter時最好是按*-spring-boot-starter的格式進行命名

mvn clean install
複製程式碼
  • 使用

將上述starter作為依賴,並配置application.properties:

dog.properties.name=dog2018
dog.properties.age=1
複製程式碼

那麼在類中只要注入DogService就能獲取到配置的值:

package net.hellomypastor.springboot.starter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/dog")
public class DogController {
    @Autowired
    private DogService dogService;

    @GetMapping("name")
    public String getDogName() {
        return dogService.getDogName();
    }

    @GetMapping("age")
    public int getDogAge() {
        return dogService.getDogAge();
    }
}
複製程式碼

測試請求結果:

http:127.0.0.1:8080/starterdemo/dog/name
結果:dog2018
http:127.0.0.1:8080/starterdemo/dog/age
結果:1
複製程式碼

好了,本期就講到這裡,下期我們講講Java9中到另一個新工具JShell,敬請期待~

Java9新特性系列(module&maven&starter)

微信公眾號:碼上論劍
請關注我的個人技術微信公眾號,訂閱更多內容

相關文章