Spring 引导应用程序 class 在测试模块 (JPMS) 中不存在

Spring Boot Application class does not existed in the test module(JPMS)

我尝试使用Java 9+内置的JPMS(Java平台模块系统)来模块化Spring启动应用程序,检查the complete sample codes here

在 IDEA 中,当 运行 测试时,它运行良好。

但是当我 运行 它通过根文件夹中的 mvn clean verify 时, greeting.application.test 将由于异常而失败“找不到包 com.example.greeting.application 和class GreetingApplication".

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project greeting-application-test: Compilation failure: Compilation fai
lure:
[ERROR] /D:/hantsylabs/spring-puzzles/modular-jpms/greeting-application-test/src/main/java/com/example/greeting/application/test/GreetingApplicationTests.java:[3,40] package com.exampl
e.greeting.application does not exist
[ERROR] /D:/hantsylabs/spring-puzzles/modular-jpms/greeting-application-test/src/main/java/com/example/greeting/application/test/GreetingApplicationTests.java:[13,19] cannot find symbo
l
[ERROR]   symbol: class GreetingApplication

模块-info.java中的greeting.application.test是这样的。

module greeting.application.test {
    requires greeting.application;

    requires spring.web;
    requires spring.core;
    requires spring.beans;
    requires spring.context;

    requires spring.boot;
    requires spring.boot.autoconfigure;
    requires spring.webflux;

    requires spring.test;
    requires spring.boot.test;
    requires spring.boot.test.autoconfigure;

    requires org.junit.jupiter;
    requires org.junit.jupiter.api;
    requires org.junit.jupiter.params;
    requires org.junit.jupiter.engine;
    requires org.junit.platform.commons;
    requires org.assertj.core;
    requires org.mockito.junit.jupiter;
    requires transitive net.bytebuddy;

    opens com.example.greeting.application.test  to spring.core, org.junit.platform.commons;
}

问题不在于“测试”模块,而是试图访问您构建的应用程序的任何其他模块。

这是由于spring-boot-maven-plugin用于repackage对应于其java模块的maven模块greeting-application引起的。

文档中的#Classifier部分进一步讲清楚了原因(我高亮显示):

By default, the repackage goal replaces the original artifact with the repackaged one. That is a sane behavior for modules that represent an application but if your module is used as a dependency of another module, you need to provide a classifier for the repackaged one. The reason for that is that application classes are packaged in BOOT-INF/classes so that the dependent module cannot load a repackaged jar’s classes.

因此,为了解决这个问题,您可以使用

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>repackage</id>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                    <configuration>
                        <classifier>exec</classifier>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

进一步引用文档并与配置更新相关:

此配置将生成两个工件:原始工件和重新打包目标生成的重新打包计数器部分。两者都会installed/deployed透明。