多层架构下Java模块依赖配置方法(含ServiceLoader场景)
Alright, let's break down how to get your nested architecture working smoothly with Java's ServiceLoader. First, let's align on the exact directory structure we're working with to avoid misconfiguration:
1. Formalize Your New Architecture
Let's lock in the example 2 directory layout to ensure we're all on the same page:
├── MainApp.jar # Your original MyApp, now serving as the entry point module └── rsc/ # Stores the full original FirstApplicationStructure ├── lib/ # External 3rd-party JARs (carried over from the original setup) └── ext/ └── lib/ # Your custom modules (previously in the original ext folder, now nested here)
2. Configure Dependencies for Modular Projects (JPMS)
If you're using Java Modules, this step is critical for ServiceLoader to cross module boundaries:
- MainApp's
module-info.java: Declare the services your module uses, plus dependencies on external and custom modules:module com.your.mainapp { // Tell the module system we use this service interface (required for ServiceLoader) uses com.your.service.MyService; // Depend on external JARs (use auto-module names for non-modular JARs) requires guava; // Example external dependency // Depend on your custom modules in rsc/ext/lib requires com.your.custom.module1; requires com.your.custom.module2; } - Custom Module's
module-info.java: Each custom module must explicitly declare it provides a service implementation:module com.your.custom.module1 { // Expose this implementation to modules that use MyService provides com.your.service.MyService with com.your.module1.MyServiceImpl; // Depend on the module that defines the service interface (MainApp here) requires com.your.mainapp; }
3. Non-Modular (Classpath) Setup
If you're sticking with the traditional classpath instead of JPMS:
- For every custom module JAR in
rsc/ext/lib, add a service provider file:- Create a folder
META-INF/servicesinside the JAR - Add a file named exactly after your service interface's full qualified name (e.g.,
com.your.service.MyService) - Inside the file, write the full qualified name of your implementation class (e.g.,
com.your.module1.MyServiceImpl)
- Create a folder
- Ensure all JARs in
rsc/libandrsc/ext/libare included in the classpath at launch.
4. Launch Command Configuration
Tell Java where to find all dependencies with these launch commands:
Modular Launch (JPMS)
# Linux/macOS java --module-path MainApp.jar:rsc/lib/*:rsc/ext/lib/* --module com.your.mainapp/com.your.mainapp.MainClass # Windows java --module-path MainApp.jar;rsc\lib\*;rsc\ext\lib\* --module com.your.mainapp/com.your.mainapp.MainClass
--module-pathincludes all JARs (MainApp, external libs, custom modules)--modulespecifies the entry point module and main class
Classpath Launch
# Linux/macOS java -cp MainApp.jar:rsc/lib/*:rsc/ext/lib/* com.your.mainapp.MainClass # Windows java -cp MainApp.jar;rsc\lib\*;rsc\ext\lib\* com.your.mainapp.MainClass
-cp(classpath) pulls in all JARs needed for the app to run
5. Critical ServiceLoader Gotchas
- Modular Encapsulation: In JPMS,
ServiceLoadercan't find implementations unless you useusesin the consuming module andprovidesin the implementation module. Skip these, and your services will be missing. - Auto-Module Names: For non-modular JARs in
rsc/lib, their auto-module name is usually the JAR filename without version numbers (e.g.,guava-32.1.2-jre.jarbecomesguava). Runjar --describe-module --file <jar-file>to confirm if you're unsure. - Path Wildcards: On Linux/macOS, use
*to include all JARs in a directory; on Windows, use*too—just ensure paths are correctly formatted.
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

