druvu-lib-loader
A type-safe component loading system built on top of Java’s ServiceLoader mechanism.
Overview
druvu-lib-loader provides dependency injection and singleton management through factories, with particular suitability for Java Platform Module System (JPMS) applications. It wraps Java’s native ServiceLoader with additional type safety and lifecycle management.
Quick Example
Here’s a real-world example showing how to create a pluggable accounting book loader:
1. Define your API interface, with a static load factory method:
public interface AccBook {
String id();
List<Account> accounts();
// Convenience factory — discovers the implementation via ServiceLoader
static AccBook load(Path path) {
return ComponentLoader.load(AccBook.class,
Dependencies.of(Path.class, path));
}
}
2. Implement ComponentFactory in your implementation module:
public class GnucashBookFactory implements ComponentFactory<AccBook> {
@Override
public AccBook createComponent(Dependencies dependencies) {
var path = dependencies.getOptionalDependency(Path.class)
.orElseThrow(() -> new IllegalArgumentException(
"Path dependency required"));
return new GnucashAccBook(path);
}
@Override
public Class<? extends AccBook> type() {
return AccBook.class;
}
}
3. Register the factory:
For non-JPMS, create META-INF/services/com.druvu.lib.loader.ComponentFactory:
com.myapp.gnucash.io.GnucashBookFactory
For JPMS, add to module-info.java:
provides com.druvu.lib.loader.ComponentFactory
with com.myapp.gnucash.io.GnucashBookFactory;
4. Use it:
AccBook book = AccBook.load(Paths.get("/path/to/file.xml"));
Core Loaders
| Loader | Purpose |
|---|---|
| ComponentLoader | Single implementation; fails if multiple exist |
| MultiComponentLoader | All implementations; returns empty list if none found |
| SingletonLoader | Application-wide services with two-phase initialization |
When multiple implementations are the point — a plugin system, an exporter per format — the same pattern flips around:
// Every registered factory receives the same Dependencies; you get all the instances
List<Exporter> exporters = MultiComponentLoader.loadAll(Exporter.class, deps);
Installation
Requirements: Java 21+
Maven:
<dependency>
<groupId>com.druvu</groupId>
<artifactId>druvu-lib-loader</artifactId>
<version>1.1.0</version>
</dependency>
Gradle:
implementation 'com.druvu:druvu-lib-loader:1.1.0'
Design Principles
- Thread-safe synchronization on target classes
- Fail-fast exception throwing
- Type-keyed dependencies — compile-time key/value typing, runtime resolution
- Immutable dependency containers
License
Apache License 2.0