This project demonstrates the Service Locator pattern in Java using the ServiceLoader API and the Java Module System (module-info.java). It consists of three modules:
api: defines theServiceAPI (an interface)impl: provides an implementation ofServiceand declares it withprovides ... with ...inmodule-info.javaapp: consumes the service viaServiceLoaderand declaresuses ...inmodule-info.java
- Java 21 (or Java 17+ should work as well)
- Maven 3.8+
service-locator-maven/
├─ pom.xml # parent/aggregator
api/
└─ src/main/java/
├─ com/example/api/User.java
├─ com/example/api/UserService.java
└─ module-info.java
impl/
└─ src/main/java/
├─ com/example/impl/UserServiceImpl.java
└─ module-info.java
app/
└─ src/main/java/
├─ com/example/app/UserController.java
├─ com/example/app/UserServiceLocator.java
└─ module-info.java
javac \
-d out/api \
api/src/main/java/module-info.java \
$(find api/src/main/java -name "*.java" -not -name "module-info.java")javac \
--module-path out/api \
-d out/impl \
impl/src/main/java/module-info.java \
$(find impl/src/main/java -name "*.java" -not -name "module-info.java")javac \
--module-path out/api \
-d out/app \
app/src/main/java/module-info.java \
$(find app/src/main/java -name "*.java" -not -name "module-info.java")
java --module-path "out/api;out/impl;out/app" --module com.example.app/com.example.app.MainIf you prefer a single javac command, put sources under a common root like:
api/
└─ src/main/java/
├─ com/example/api/User.java
├─ com/example/api/UserService.java
└─ module-info.java
impl/
└─ src/main/java/
├─ com/example/impl/UserServiceImpl.java
└─ module-info.java
app/
└─ src/main/java/
├─ com/example/app/UserController.java
├─ com/example/app/UserServiceLocator.java
└─ module-info.java
Then compile and run:
javac --module-source-path src -d out -m com.example.api,com.example.impl,com.example.app
java --module-path out --module com.example.app/com.example.app.Main "Hello"