使用Jigsaw模块运行Spring Boot与JDK9

7
这个应用程序有什么问题。我认为classpath jars和module jars混合在一起是有效的。对于所有没有显式module-info的jar包都会自动成为一个自动模块吗?当我删除我的module-info.java文件时,它可以工作。因为在这种情况下IDEA使用了classpath。
Java(TM) SE运行时环境(版本9+176)。
IntelliJ IDEA 2017.1.4
module-info.java
module test {
    requires spring.boot.autoconfigure;
    requires spring.boot;
}

App.java

package com.foo.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

pom.xml

<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.foo.test</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.M2</version>
    </parent>

    <name>test</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.9</maven.compiler.source>
        <maven.compiler.target>1.9</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

在主线程中出现异常:java.lang.IllegalArgumentException: 无法实例化接口org.springframework.context.ApplicationContextInitializer:org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer。此问题是由以下原因引起的:
在spring.boot@2.0.0.M2/org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:439)处创建Spring工厂实例时发生了错误;
使用spring.boot@2.0.0.M2/org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:418)获取Spring工厂实例时发生错误;
使用spring.boot@2.0.0.M2/org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:409)获取Spring工厂实例时发生错误;
在spring.boot@2.0.0.M2/org.springframework.boot.SpringApplication.(SpringApplication.java:266)实例化Spring应用程序时发生错误;
在spring.boot@2.0.0.M2/org.springframework.boot.SpringApplication.(SpringApplication.java:247)实例化Spring应用程序时发生错误;
运行spring.boot@2.0.0.M2/org.springframework.boot.SpringApplication.run(SpringApplication.java:1245)时发生错误;
在spring.boot@2.0.0.M2/org.springframework.boot.SpringApplication.run(SpringApplication.java:1233)时发生错误;
错误的根本原因是java.lang.NoClassDefFoundError: java/sql/SQLException
这是由于spring.beans@5.0.0.RC2/org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:145)处创建类实例时发生了错误。
以上错误继承自java.lang.ClassNotFoundException: java.sql.SQLException,是由于java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)未能加载java.sql.SQLException。

强烈建议根据您的包命名模块。例如,module com.foo.test {...} - axiopisty
4个回答

7

我认为spring.boot是一个自动模块。自动模块不会声明它的依赖关系,因此您需要使用--add-modules来确保解析任何需要的显式模块。如果spring.boot是一个显式模块,那么我认为它将requires java.sql,那么您就不会遇到这个问题。


VM参数:--add-modules=java.sql也可以工作,但这不是你的意思吧? - Daniel
4
是的,我的意思是使用--add-modules=java.sql来确保解析java.sql模块。否则,它将无法解析,因为没有模块需要它。您通过在您的模块中添加requires java.sql来解决了这个问题,但这是不必要的(并且一旦spring.boot迁移到显式模块,就不再需要)。 - Alan Bateman
Alex Buckley在devoxxUS(JDK 9模块化开发)中告诉我们自动模块:“......需要一切,它们彼此需要,它们需要jdk映像中的所有模块以及您的所有模块,并且它们导出其包......”(引用类似于他所说的)。我仍然不明白为什么我必须添加java.sql模块。无论何时需要时,为什么只有java.sql?我很确定spring.boot还有更多模块。requires和“declare dependences”不是相同的吗? - Daniel

5

终于,我搞定了...我的module-info应该长成这样:

module test {
    requires java.sql; // my real problem solved with this
    requires spring.boot.autoconfigure;
    requires spring.boot;
    exports com.foo.test; // subsequent error 1: beeing accessible for some spring modules
    opens com.foo.test to spring.core; // subsequent error 2: beeing accessible for spring.core in a deep reflection way
}

有人能解释一下为什么我在自己的模块中没有使用 java.sql,却必须要加上 requires java.sql; 吗?


2
因为 spring 需要 java.sql,而 spring 是自动模块,它没有声明需要哪些内容才能工作,所以您需要通过 --add-modules java.sql 或在您自己的模块中使用 requires java.sqljava.sql 包含到模块图中。 - David

1

当我从Java 8升级到Java 11时,遇到了同样的问题。

通过在Intellij运行配置中选择不同的选项来解决: 缩短命令行


-2
这几乎肯定是因为您缺少用于MySql的jdbc驱动程序jar。 您需要使用此依赖项 :-
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>6.0.5</version>
</dependency>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接