Java9模塊化學習筆記三之遷移到Java9

java[c]命令行參數文件

鑑於遷移到java9後可能須要很長的命令行參數,有些os會限制命令行長度,java9支持定義一個命令行參數文件。使用方式:java

java @arguments.txt

arguments.txt內容(每一個選項一行):spring

-cp application.jar:javassist.jar
--add-opens java.base/java.lang=ALL_UNNAMED
--add-exports java.base/sun.security.x509=ALL_UNNAMED
-jar application.jar

Jdeps

前面咱們說過之前不少時候咱們或第三方庫使用jdk不推薦使用的內部類,好比sun.,jdk.internal.,在jdk9以後這些類被強封裝了,爲了保持兼容性,默認運行運行時訪問,其行爲能夠經過java選項--illegal-access=值,控制,默認值爲permit,其餘可選值有warn,debug,denysql

除此以外還有些類被移除了,好比sun.misc.Base64Decoder/Base64Encoder, 不過提供了替代方案java.util.Encoder
咱們能夠藉助於jdeps工具來發現這些問題,使用方式:express

jdeps -jdkinternals Xxx.class

注意:jdeps只能用於分析class文件或jar,不能用於分析源碼文件apache

使用jdeps分析 classpath-based依賴:
.
├── jars
│ ├── jackson-annotations-2.8.8.jar
│ └── jackson-core-2.8.8.jar
| └── jackson-databind-2.8.8.1.jar
└── outapi

├── demo
     ├── Book.class
     └── Main.class

好比分析上面的這個模塊:app

jdeps -recursive -summary -cp lib/*.jar out

-recusive表明requires transitive的也會被分析,-summary表明彙總依賴信息,否則會打印很長的依賴信息, -cp classpath, out就是須要被分析的class/jar文件路徑maven

tjw$ jdeps -recursive -summary -cp lib/*.jar out
jackson-annotations-2.8.8.jar -> java.base
jackson-core-2.8.8.jar -> java.base
jackson-databind-2.8.8.jar -> lib/jackson-annotations-2.8.8.jar
jackson-databind-2.8.8.jar -> lib/jackson-core-2.8.8.jar
jackson-databind-2.8.8.jar -> java.base
jackson-databind-2.8.8.jar -> java.desktop
jackson-databind-2.8.8.jar -> java.logging
jackson-databind-2.8.8.jar -> java.sql
jackson-databind-2.8.8.jar -> java.xml
out -> lib/jackson-databind-2.8.8.jar
out -> java.base

上面的依賴分析顯示,咱們的代碼直接依賴jackson-databind,故而咱們在遷移到模塊時應將jackson-databind做爲Automic Module,故而遷移到模塊化後的代碼結構以下:
.
├── lib
│ ├── jackson-annotations-2.8.8.jar
│ └── jackson-core-2.8.8.jar
├── mods
│ └── jackson-databind-2.8.8.jar //這裏會被做爲Automic Module
└── src模塊化

└── books
    ├── demo
    │   ├── Book.java
    │   └── Main.java
    └── module-info.java

module-info.java內容:工具

module books {
    requires jackson.databind;
    opens demo;
}

使用jdeps分析 module-based依賴:
jdeps -module-path out:mods -m books

注意:使用jdeps咱們還能夠利用-dotoutput選項來輸出模塊的依賴關係圖做爲文件保存

除了分析依賴以外,jdeps還能夠生成module-info.java,這在遷移已有三方庫的時候特別有用:

jdeps --generate-module-info ./out mylibrary.jar

JAXB與其餘JavaEE API

java.se.ee模塊
clipboard.png

Automatic Modules

除了以前說的unamed modules,還有一種叫automatic modules,這是爲解決已有三方庫遷移到模塊化的問題。已有三分庫能夠自動轉成模塊,只要在啓動時將jar放在指定--module-path路徑中,便會自動變成automatic module。
automatic module的特性:一、該module自己是open的;二、該module的依賴由開發者自行解決,編譯時沒法找出相關問題;三、automatic module與explicit module的區別在於,前者能夠無限制訪問unamed module,然後者遵循模塊的封裝性原則。
automatic modules模塊名: 好比jackson-databind-2.8.8.jar,在java定義它成模塊時,首先須要掃描MATA-INF/MANIFEST.MF中的Automatic-Module-Name字段,若是沒有這個字段,那麼就以jar文件名字做爲模塊名,好比jackson-databind-2.8.8.jar的模塊名就是jackson.databind,轉成模塊名時會把-替換成. 而後版本號會被忽略掉。

clipboard.png

遷移示例:遷移Spring And Hibernate

未遷移代碼就不列出來了,遷移後的代碼結構以下:

.
├── README.md
├── lib
│   ├── hsqldb-2.3.4.jar
│   ├── ...
│   ├── slf4j-api-1.7.21.jar
│   ├── slf4j-simple-1.7.21.jar
│   ├── spring-aop-4.3.2.RELEASE.jar
│   ├── spring-beans-4.3.2.RELEASE.jar
│   ├── spring-core-4.3.2.RELEASE.jar
│   ├── spring-expression-4.3.2.RELEASE.jar
│   ├── spring-jdbc-4.3.2.RELEASE.jar
│   └── spring-orm-4.3.2.RELEASE.jar
├── mods
│   ├── hibernate-core-5.2.2.Final.jar
│   ├── hibernate-jpa-2.1-api-1.0.0.Final.jar
│   ├── javassist-3.20.0-GA.jar
│   ├── javax.inject-1.jar
│   ├── spring-context-4.3.2.RELEASE.jar
│   └── spring-tx-4.3.2.RELEASE.jar
├── run.sh
└── src
    └── bookapp
        ├── books
        │   ├── api
        │   │   ├── entities
        │   │   │   └── Book.java
        │   │   └── service
        │   │       └── BooksService.java
        │   └── impl
        │       ├── entities
        │       │   └── BookEntity.java
        │       └── service
        │           └── HibernateBooksService.java
        ├── bookstore
        │   ├── api
        │   │   └── service
        │   │       └── BookstoreService.java
        │   └── impl
        │       └── service
        │           └── BookstoreServiceImpl.java
        ├── log4j2.xml
        ├── main
        │   └── Main.java
        ├── main.xml
        └── module-info.java

module-info.java內容

module bookapp {
    requires spring.context;
    requires spring.tx;

    requires javax.inject;

    requires hibernate.core;
    requires hibernate.jpa;

    exports books.api.entities;
    exports books.api.service;
    opens books.impl.entities;
    opens books.impl.service;

    exports bookstore.api.service;
    opens bookstore.impl.service;
}

run.sh內容

CP=lib/antlr-2.7.7.jar:
...
CP+=lib/slf4j-api-1.7.21.jar:
CP+=lib/slf4j-simple-1.7.21.jar:
CP+=lib/spring-aop-4.3.2.RELEASE.jar:
CP+=lib/spring-beans-4.3.2.RELEASE.jar:
CP+=lib/spring-core-4.3.2.RELEASE.jar:
CP+=lib/spring-expression-4.3.2.RELEASE.jar:
CP+=lib/spring-jdbc-4.3.2.RELEASE.jar:
CP+=lib/spring-orm-4.3.2.RELEASE.jar

$JAVA_HOME/bin/javac -cp $CP \
      --module-path mods \
      --add-modules java.naming \
      -d out         \
      --module-source-path src \
      -m bookapp

cp $(find src -name '*.xml') out/bookapp

$JAVA_HOME/bin/java -cp $CP \
     --module-path mods:out       \
     --add-modules java.xml.bind,java.sql \
     --add-opens java.base/java.lang=javassist \
     -m bookapp/main.Main

咱們還能夠將本身的應用拆分爲多個模塊
演化圖以下:
clipboard.png
clipboard.png
clipboard.png

遷移Library到模塊化

遷移方式一,遷移爲Automatic Module,適用於沒有源碼的情形:
模塊名:在MANIFEST.MF中定義

Automatic-Module-Name: com.javamodularity.modulename
jar -cfm mylibrary.jar META-INF/MANIFEST.MF -C out/ .

你也可使用maven插件

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifestEntries>
                <Automatic-Module-Namec>com.mymodule</Automatic-Module-Name>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

遷移方式二,遷移爲explicit module,適用於庫的做者或者有源碼的情形:
首先借助jdeps生成module-info.java,而後進行簡單修改

jdeps --generate-module-info ./out mylibrary.jar  //你也可使用--generate-open-module選項

方式三,遷移爲explicit module,即便沒有源碼:

mkdir mylibrary
cd mylibrary
jar -xf ../mylibrary.jar
cd ..
javac -d mylibrary out/mylibrary/module-info.java
jar -uf mylibrary.jar -C mylibrary module-info.class

針對不一樣版本發佈 javac --release 版本號 好比 javac --release 8

模塊化開發工具

maven

.
├── README.md
├── algorithm.api
│   ├── pom.xml
│   └── src
│       └── main
│           └── java
│               ├── javamodularity
│               │   └── easytext
│               │       └── algorithm
│               │           └── api
│               │               ├── Analyzer.java
│               │               ├── Preprocessing.java
│               │               └── SyllableCounter.java
│               └── module-info.java
├── cli
│   ├── README.adoc
│   ├── pom.xml
│   └── src
│       └── main
│           ├── java
│           │   ├── javamodularity
│           │   │   └── easytext
│           │   │       └── cli
│           │   │           └── Main.java
│           │   └── module-info.java
│           └── resources
│               └── test.txt
├── gui
│   ├── gui.iml
│   ├── pom.xml
│   └── src
│       └── main
│           └── java
│               ├── javamodularity
│               │   └── easytext
│               │       └── gui
│               │           └── Main.java
│               └── module-info.java
├── pom.xml
└── run.sh
<build>
      <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>
</build>

使用maven執行模塊

<build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.6.0</version>
        <executions>
          <execution>
            <goals>
              <goal>exec</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <executable>${JAVA_HOME}/bin/java</executable>
          <arguments>
            <argument>--module-path</argument>
            <modulepath/>
            <argument>--module</argument>
            <argument>easytext.cli/javamodularity.easytext.cli.Main</argument>
            <argument>${easytext.file}</argument>
          </arguments>
        </configuration>
      </plugin>
    </plugins>
  </build>

具體執行命令 mvn exec:exec

相關文章
相關標籤/搜索