真棒:使用Java 11实现应用的模块化

Java 11带来成熟的模块化系统,OSGI丢一边去吧,为什么要迁移到模块系统?

1. 模块能带来可靠的配置 – 新的模块系统是需要在程序组件里明确声明依赖的方法,这种替代料以前默认的但是脆弱的、容易出错的类路径机制,好像只要把Jar包放入classpath就大功告成了,其实没有那么容易,版本冲突等等非常烦人。

2.强封装 – 允许组件声明哪些公共类型可供外部其他组件访问,哪些不可被访问。

3.为你的应用程序创建最小的JRE映像。

4.减少应用程序内存占用量。

5.优化应用程序启动时间

以 Spring PetClinic为案例:

git clone git@github.com:spring-projects/spring-petclinic.git

看看具体怎么实现模块化:

1. 在src / main / java目录中创建一个名为module-info.java的文件,其中包含以下内容:

module spring.petclinic {
}

现在,尝试编译应用程序时,您会看到很多错误,而在以前java 8中则不会出现。这意味着应用程序表现为模块化布局,并且必须混入模块功能进行了编译和运行。

可以使用Maven依赖项插件解析目标列出当前在类路径中的所有模块名称,并将它们添加到module-info中:

./mvnw compile org.apache.maven.plugins:maven-dependency-plugin:3.1.1:resolve

填入module-info以后变成下面:

open module spring.petclinic {
    requires cache.api;

    requires java.activation;
    requires java.instrument;
    requires java.persistence;
    requires java.sql;
    requires java.transaction;
    requires java.validation;
    requires java.xml.bind;

    requires org.hibernate.validator;

    requires spring.beans;
    requires spring.boot;
    requires spring.boot.autoconfigure;
    requires spring.context;
    requires spring.core;
    requires spring.data.commons;
    requires spring.data.jpa;
    requires spring.tx;
    requires spring.web;
    requires spring.webmvc;

    requires jdk.unsupported;
}

open关键词是用于Spring和Hibernate的反射机制.

2.使用maven-jar-plugin创建应用程序jar(仅限于类)并将其复制到modules目录:

<plugin>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
        <outputDirectory>
            ${project.build.directory}/modules
        </outputDirectory>
    </configuration>
</plugin>

3.使用maven-dependency-plugin复制运行时的依赖到modules目录:


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/modules
</outputDirectory>
<includeScope>runtime</includeScope>
<excludeArtifactIds>
spring-boot-devtools
</excludeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>

spring-boot-devtools 应该从模块中排除

4.升级 java.persistence 和 java.transaction版本:

<dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.1-api</artifactId>
    <version>1.0.2.Final</version>
</dependency>
<dependency>
    <groupId>org.jboss.spec.javax.transaction</groupId>
    <artifactId>jboss-transaction-api_1.2_spec</artifactId>
    <version>1.1.1.Final</version>
</dependency>

 

在spring-boot-starter-data-jpa中排除对旧javax.transaction的依赖项:

<exclusions>
    <exclusion>
        <artifactId>javax.transaction-api</artifactId>
        <groupId>javax.transaction</groupId>
    </exclusion>

5.修改maven-surefire-plugin配置以禁用分叉进程

<configuration>
    <forkCount>0</forkCount>
</configuration>

当存在module-info.java并且启用了fork进程时,surefire会创建一个包含模块和未命名模块的混合类路径,从而导致模块可见性问题并阻止应用程序启动。

6.打包并测试应用程序。

./mvnw clean package

7.使用Java模块系统运行应用程序:

java --add-opens java.base/java.lang=spring.core,javassist /
--module-path target/modules /
--module spring.petclinic/org.springframework.samples.petclinic.PetClinicApplication

由于Spring和Hibernate依赖项需要JDK反射访问,因此需要–add -opens。

8.如果使用以下命令设置模块main-class属性,则可以删除使用module参数指定的主类:


jar --update /
--file=target/modules/spring-petclinic-2.0.0.BUILD-SNAPSHOT.jar /
--main-class=org.springframework.samples.petclinic.PetClinicApplication

9.为了自动执行上一步,您可以添加exec-maven-plugin:


<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>module-main-class</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>jar</executable>
<arguments>
<argument>
--update
</argument>
<argument>
--file=${project.build.directory}/modules/${project.build.finalName}.jar
</argument>
<argument>
--main-class=org.springframework.samples.petclinic.PetClinicApplication
</argument>
<argument>
--module-version=${project.version}
</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>

10.现在您可以不需要自己声明主类的情况下运行应用程序:


./mvnw clean package
java --add-opens java.base/java.lang=spring.core,javassist /
--module-path=target/modules /
--module spring.petclinic

原文 

https://www.jdon.com/49683

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 真棒:使用Java 11实现应用的模块化

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址