序
本文主要研究下如何在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那種宣告方式。