如何为Java 9模块组织公共依赖?Maven多模块复用配置疑问
module-info.java? Great question—let's break this down clearly, because there's a common misunderstanding here about how Maven parent modules interact with the Java Module System.
First: Why Your Root Parent Module Can't Host a Shared module-info.java
Maven parent modules are almost always configured with <packaging>pom</packaging>, which means they don't compile any Java code or produce a JAR artifact. Even if you manually add a src/main/java/module-info.java to the root module, Maven won't compile it into a valid Java module. Your submodules can't requires a module that doesn't exist as a compiled JAR, so this approach won't work.
Root parent modules are meant for Maven-level configuration reuse (like dependency versions, plugins, etc.), not for Java module system declarations.
Solutions to Reuse Common Module Dependencies
If you want to avoid repeating requires declarations across submodules, you have two solid options:
1. Use Maven dependencyManagement for Version Consistency (Simplest)
You're already adding common dependencies to the root pom's <dependencies> block, but switching to <dependencyManagement> is better for version control:
- In your root pom.xml:
<dependencyManagement> <dependencies> <!-- Declare common dependencies with fixed versions here --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>32.1.3-jre</version> </dependency> </dependencies> </dependencyManagement> - In each submodule's pom.xml, add the dependency without specifying the version:
<dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> </dependencies> - Note: You'll still need to add
requires com.google.guava;to each submodule'smodule-info.java—the Java Module System doesn't inheritrequiresdeclarations from Maven dependencies. This ensures each module explicitly declares its dependencies (a core principle of the module system).
2. Create a Dedicated "Dependency Aggregator" Module (For Reusable requires Declarations)
This is the way to achieve actual module-level reuse of requires statements:
- Create a new submodule (e.g., named
common-deps) with<packaging>jar</packaging>(it needs to be a valid Java module). - In its
module-info.java, userequires transitivefor all common dependencies. This makes those dependencies available to any module thatrequiresthis aggregator:module common.deps { requires transitive com.google.guava; requires transitive org.apache.commons.lang3; // Add all other shared dependencies here } - In each submodule's pom.xml, add a dependency on
common-deps:<dependencies> <dependency> <groupId>your.group.id</groupId> <artifactId>common-deps</artifactId> <version>${project.version}</version> </dependency> </dependencies> - In each submodule's
module-info.java, replace all individualrequiresstatements with a single line:requires common.deps;
All the transitive dependencies from common-deps will now be accessible in the submodule.
Key Note About requires transitive
Use requires transitive only for dependencies that submodules need to use directly. If a dependency is only used internally by common-deps (unlikely here, since it's an aggregator), use a plain requires instead—this prevents unnecessary dependencies from leaking to submodules.
内容的提问来源于stack exchange,提问作者Nickolay-Maryan Sokolovksy

