使用maven構建java9 service例項

go4it發表於2019-02-21

本文主要研究下如何在maven裡頭構建java9 multi module及service例項

maven

整個工程跟傳統maven多module的工程結構一樣,java9的一個module對應maven project的一個module。下面是根目錄下的pom檔案:

<?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>

    <groupId>com.example</groupId>
    <artifactId>java9-service-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <modules>
        <module>consumer-demo</module>
        <module>service-sort</module>
        <module>service-sort-bubble</module>
        <module>service-sort-merge</module>
    </modules>
    <packaging>pom</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--讓intellij能夠正確編譯java9,不然老是變回使用1.5-->
        <maven.compiler.source>9</maven.compiler.source>
        <maven.compiler.target>9</maven.compiler.target>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.6.1</version>
                    <configuration>
                        <release>9</release>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>
複製程式碼

這裡管理了一個maven-compiler-plugin,配置release為9,因為java9支援multi release,可以同時支援多個java版本,這裡編譯為java9版本。

service-sort

這個是service介面module

module service.sort {
    exports service.sort;
    uses service.sort.SortService;
}
複製程式碼

這裡同時宣告uses SortService表示是它需要在這個module裡頭使用ServiceLoader去載入service例項

public interface SortService {
    public <T extends Comparable> List<T> sortList(List<T> list);

    public static SortService getProviderInstanceLazy() {
        Stream<Provider<SortService>> providers = ServiceLoader.load(SortService.class)
                .stream();
        //provider方法等到get的時候才會例項化
        SortService service = providers.map(Provider::get)
                .findAny()
                .orElse(null);
        return service;
    }
}
複製程式碼

這裡在宣告介面的同時,也增加了靜態方法,用於載入service例項。

service-sort-bubble

  • maven
<?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">
    <parent>
        <artifactId>java9-service-demo</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>service-sort-bubble</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>service-sort</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>
複製程式碼

這裡新增對api包的依賴

  • module-info.java
module service.sort.bubble {
    requires service.sort;
    provides service.sort.SortService with sort.impl.bubble.BubbleSort;
}
複製程式碼

這裡宣告瞭BubbleSort提供了SortService的實現

  • BubbleSort
public class BubbleSort implements SortService {

    public <T extends Comparable> List<T> sortList(List<T> list) {
        System.out.println("use BubbleSort");
        for (int outer = 0; outer < list.size() - 1; outer++) {
            for (int inner = 0; inner < list.size()-outer-1; inner++) {
                if (list.get(inner).compareTo(list.get(inner + 1)) > 0)  {
                    swap(list, inner);
                }
            }
        }
        return list;
    }

    private <T> void swap(List<T>list, int inner) {
        T temp = list.get(inner);
        list.set(inner, list.get(inner + 1));
        list.set(inner + 1, temp);
    }
}
複製程式碼

service-sort-merge

  • maven
<?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">
    <parent>
        <artifactId>java9-service-demo</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>service-sort-merge</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>service-sort</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
複製程式碼
  • module-info.java
module service.sort.merge {
    requires service.sort;
    provides service.sort.SortService with sort.impl.merge.MergeSort;
}
複製程式碼

這裡宣告瞭MergeSort為SortService介面的實現

  • MergeSort
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;
import service.sort.SortService;

public class MergeSort implements SortService {

    public <T extends Comparable> List<T> sortList(List<T> list) {
        System.out.println("using MergeSort");
        Collections.sort(list);
        return list;
    }
}
複製程式碼

consumer

  • maven
<?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">
    <parent>
        <artifactId>java9-service-demo</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>consumer-demo</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>service-sort</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>
複製程式碼

注意這裡沒有新增實現類的依賴

  • module-info.java
module consumer {
    requires service.sort;
}
複製程式碼
  • Main
public class Main {

    public static void main(String[] args) {

        System.out.println("sort service consumer started.");
        List<Integer> data = new ArrayList<Integer>();
        data.add(5);
        data.add(3);
        data.add(10);
        data.add(2);
        data.add(8);

        SortService sortService = SortService.getProviderInstanceLazy();
        if (sortService != null) {
            sortService.sortList(data);
        }
        System.out.println(data);
        System.out.println("finish");
    }
}
複製程式碼

編譯及執行

  • 編譯
mvn clean install
複製程式碼

這裡是在根目錄下執行

  • 使用bubble
java --module-path ./consumer-demo/target/consumer-demo-0.0.1-SNAPSHOT.jar:./service-sort/target/service-sort-0.0.1-SNAPSHOT.jar:./service-sort-bubble/target/service-sort-bubble-0.0.1-SNAPSHOT.jar --module consumer/consumer.Main
複製程式碼

注意這裡新增了bubble的jar到module-path

輸出

sort service consumer started.
use BubbleSort
[2, 3, 5, 8, 10]
finish
複製程式碼
  • 使用merge
java --module-path ./consumer-demo/target/consumer-demo-0.0.1-SNAPSHOT.jar:./service-sort/target/service-sort-0.0.1-SNAPSHOT.jar:./service-sort-merge/target/service-sort-merge-0.0.1-SNAPSHOT.jar --module consumer/consumer.Main
複製程式碼

注意這裡新增了merge的jar到module-path

輸出

sort service consumer started.
using MergeSort
[2, 3, 5, 8, 10]
finish
複製程式碼
  • 兩個service實現都新增
java --module-path ./consumer-demo/target/consumer-demo-0.0.1-SNAPSHOT.jar:./service-sort/target/service-sort-0.0.1-SNAPSHOT.jar:./service-sort-bubble/target/service-sort-bubble-0.0.1-SNAPSHOT.jar:./service-sort-merge/target/service-sort-merge-0.0.1-SNAPSHOT.jar --module consumer/consumer.Main
複製程式碼

或者

java --module-path ./consumer-demo/target/consumer-demo-0.0.1-SNAPSHOT.jar:./service-sort/target/service-sort-0.0.1-SNAPSHOT.jar:./service-sort-merge/target/service-sort-merge-0.0.1-SNAPSHOT.jar:./service-sort-bubble/target/service-sort-bubble-0.0.1-SNAPSHOT.jar --module consumer/consumer.Main
複製程式碼

輸出

sort service consumer started.
use BubbleSort
[2, 3, 5, 8, 10]
finish
複製程式碼

發現貌似跟新增到path的順序沒有關係,即使把merge的jar包放在前面,也是使用bubble

小結

在java6的時候就已經有ServiceLoader了,不過那個時候是依賴在jar包的META-INF/services目錄下建立一個service介面全路徑名稱的檔案,裡頭寫上實現類的全路徑名稱。java9對在引入模組化後也支援在module-info.java裡頭宣告service的提供方和消費者資訊,這樣模組系統可以支援ServiceLoader,不需要使用原來的META-INF那種宣告方式。

doc

相關文章