【问题标题】:Spring NoSuchBeanDefinitionException when switching to JPMS (Java Platform Module System)切换到 JPMS(Java 平台模块系统)时出现 Spring NoSuchBeanDefinitionException
【发布时间】:2020-10-02 14:20:13
【问题描述】:

我正在尝试将一个大型项目迁移到 JPMS(Java 平台模块系统)。

它包含一些给我带来麻烦的 Spring 组件。 我创建了一个test repo 来演示这个问题。当我删除 module-info.java 文件时,它工作得很好,如TestControllerTest.java 中的测试所示。但是,如果我添加 module-info.java 那么它会停止工作并出现以下异常:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'RESTConfiguration': Unsatisfied dependency expressed through field 'fooAuthenticationProvider'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.spacemetric.spring.jpmstest.auth.FooAuthenticationProvider' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at spring.beans@5.2.6.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
at spring.beans@5.2.6.RELEASE/org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
at … 

堆栈跟踪似乎表明ApplicationContext 无法找到@Autowired 实现。我已经打开了整个模块进行深度反思。我高度未受教育的猜测是,这可能与类路径与模块路径有关,但我不知道该怎么做。

module-info.java文件如下:

open module com.spacemetric.spring.jpmstest {       
    requires spring.core;
    requires spring.context;
    requires spring.beans;
    requires spring.security.config;
    requires spring.security.web;
    requires spring.webmvc;
    requires spring.security.core;
    requires javax.servlet.api;
    requires spring.web;
}

以下是 Eclipse 用来运行测试的命令行(根据要求):

C:\程序 文件\Java\java-11-openjdk-11.0.7.10-1.windows.redhat.x86_64\bin\javaw.exe -ea --add-opens com.spacemetric.spring.jpmstest/com.spacemetric.spring.jpmstest=ALL-UNNAMED --add-modules=ALL-MODULE-PATH -Dfile.encoding=UTF-8 -p "C:\dev\source\spring-jpms-test\target\classes;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-core\5.2.6.RELEASE\spring-core-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\security\spring-security-web\5.3.2.RELEASE\spring-security-web-5.3.2.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\security\spring-security-core\5.3.2.RELEASE\spring-security-core-5.3.2.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-beans\5.2.6.RELEASE\spring-beans-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-context\5.2.6.RELEASE\spring-context-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring- web\5.2.6.RELEASE\spring-web-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\security\spring-security-config\5.3.2.RELEASE\spring-security-config-5.3.2.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-webmvc\5.2.6.RELEASE\spring-webmvc-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\javax\servlet\javax.servlet-api\3.1.0\javax.servlet-api-3.1.0.jar" -classpath "C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-jcl\5.2.6.RELEASE\spring-jcl-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-aop\5.2.6.RELEASE\spring-aop-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-expression\5.2.6.RELEASE\spring-expression-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.7.0\junit-jupiter-engine-5.7.0.jar;C:\Users\Oscar Haglund.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;C:\Users\Oscar Haglund.m2\repository\org\junit\platform\junit-platform-engine\1.7.0\junit-platform-engine-1.7.0.jar;C:\Users\Oscar Haglund.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\Oscar Haglund.m2\repository\org\junit\platform\junit-platform-commons\1.7.0\junit-platform-commons-1.7.0.jar;C:\Users\Oscar Haglund.m2\repository\org\junit\jupiter\junit-jupiter-api\5.7.0\junit-jupiter-api-5.7.0.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\spring-test\5.2.6.RELEASE\spring-test-5.2.6.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\org\springframework\restdocs\spring-restdocs-mockmvc\2.0.5.RELEASE\spring-restdocs-mockmvc-2.0.5.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\ org\springframework\restdocs\spring-restdocs-core\2.0.5.RELEASE\spring-restdocs-core-2.0.5.RELEASE.jar;C:\Users\Oscar Haglund.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.5\jackson-databind-2.9.5.jar;C:\Users\Oscar Haglund.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\Users\Oscar Haglund.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.5\jackson-core-2.9.5.jar;C:\Users\Oscar Haglund.m2\repository\org\mockito\mockito-junit-jupiter\3.5.10\mockito-junit-jupiter-3.5.10.jar;C:\Users\Oscar Haglund.m2\repository\org\mockito\mockito-core\3.5.10\mockito-core-3.5.10.jar;C:\Users\Oscar Haglund.m2\repository\net\bytebuddy\byte-buddy\1.10.13\byte-buddy-1.10.13.jar;C:\Users\Oscar Haglund.m2\repository\net\bytebuddy\byte-buddy-agent\1.10.13\byte-buddy-agent-1.10.13.jar;C:\Users\Oscar Haglund.m2\repository\org\objenesis\objenesis\3.1\objenesis-3.1.jar;C:\Users\Oscar Haglund.m2\repository\org\junit\platform\junit-platform-launcher\1.7.0\junit-platform-launcher-1.7.0.jar;C:\dev\eclipse\configuration\org.eclipse.osgi\259 \0.cp;C:\dev\eclipse\configuration\org.eclipse.osgi\257\0.cp" --patch-module "com.spacemetric.spring.jpmstest=C:\dev\source\spring-jpms-test\target\test-classes" --add-reads com.spacemetric.spring.jpmstest=ALL-UNNAMED org.eclipse.jdt.internal.junit.runner.RemoteTestRunner -version 3 -port 55245 -testLoaderClass org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader -loaderpluginname org.eclipse.jdt.junit5.runtime -classNames com.spacemetric.spring.jpmstest.TestControllerTest

【问题讨论】:

  • Your README 谈到了用于“测试类”的 module-info.java。问题:(1) 您需要在测试目录中有一个 module-info.java 的用例是什么? (2) 应该运行什么命令来产生错误? (3) 这是否与 your other JPMS issue有关? TIA。
  • ...堆栈跟踪似乎表明 ApplicationContext 无法找到 @Autowired 实现...“ -​​ 恐怕您猜错了。当你回到我身边并回答我的问题时,我可能已经能够详细说明我的意思了。 TIA。
  • (1) 对不清楚的自述文件表示歉意。 module-info.java 用于源目录(src/main/java)和我创建的最小实现来展示我在一个更大的项目中遇到的异常。自述文件是指可以运行以产生异常的单元测试。 (2) 在您选择的 IDE 中运行单元测试类。我已经更新了原始文本以包含 Eclipse 用来运行测试的命令。 (3) 到目前为止,他们都曾尝试转换同一个存储库。这些问题出现在不同的模块中。
  • (1)...module-info.java 用于源目录(src/main/java)...“——也许@Eugene 可能没有跳转到如果您的 README 内容为:“…TestControllerTest 如果从 src/main/java 中删除了 module-info.java 文件,则他的回答会得出错误的结论” — „… (2) 在你的 IDE 中运行单元测试类……“——这是另一个启示。您最初从未提到过 IDE。我从终端构建了您的 MRE。测试成功——“…Eclipse 用来运行测试的命令…”——重现错误的Eclipse 菜单选项步骤是什么?你是新来的。你会学到的。 TIA

标签: java spring java-module java-platform-module-system


【解决方案1】:

首先将module-info.java 放入src/main/java,而不是src/test/java。我也将其稍微更改为:

module spring.jpms.test {
   requires spring.core;
   requires spring.context;
   requires spring.beans;
   requires spring.security.config;
   requires spring.security.web;
   requires spring.webmvc;
   requires spring.security.core;
   requires javax.servlet.api;
   requires spring.web;

   opens com.spacemetric.spring.jpmstest;

}

但无论如何,这只能“部分”解决,因为:

欢迎来到modulesspring(或一般工具)的相当粗略的现实。看看here, where people have the same problems。我发现唯一可行的解​​决方案是:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
        <useModulePath>false</useModulePath>
    </configuration>
</plugin>

这适用于mvn clean install(和junit5),我还没有尝试或玩足够的intellij 使其工作。

【讨论】:

  • 撤销open module…的理由是什么?您的 opens com.spacemetric.spring.jpmstest 建议假定您已经知道(无需询问真正的项目只有 1 个 pkg。它可能有 10 个,需要全部打开。在那个用例中,open module… 更简单。您假设 OP 的用例不需要在主模块中进行测试?基于什么?我已经要求@oscar.haglund 澄清他的用例。但在他回复之前,任何建议都是不成熟和不知情的。 — “……模块的相当粗暴的现实……” — 甚至是残酷的现实。两者都相当复杂恕我直言。 TIA。
猜你喜欢
  • 1970-01-01
  • 2015-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 1970-01-01
  • 2012-04-12
  • 2018-06-20
相关资源
最近更新 更多