Java › Java Platform Module System (JPMS)
How does the ServiceLoader/Service Provider Interface pattern integrate with JPMS using the 'uses' and 'provides ... with' directives, replacing the older META-INF/services file-based mechanism?
IntermediateAnswer
Under JPMS, a module declares that it CONSUMES a service via uses ServiceInterface (letting it use ServiceLoader.load() to discover implementations), and a module PROVIDING an implementation declares provides ServiceInterface with ImplementationClass -- this JPMS-native declaration mechanism replaces (though doesn't strictly require replacing, for backward compatibility) the older convention-based META-INF/services/ text file approach, giving the module system full, explicit visibility into service provider relationships as part of the formal module graph, rather than relying on a loosely-coupled convention the module system itself has no direct awareness of.
// Consumer module
module com.example.app {
uses com.example.spi.PaymentProcessor; // declares it will consume this service
}
// Provider module
module com.example.stripe.provider {
provides com.example.spi.PaymentProcessor with com.example.stripe.StripePaymentProcessor;
}
// Consumer code, unchanged from the pre-JPMS pattern
ServiceLoader<PaymentProcessor> loader = ServiceLoader.load(PaymentProcessor.class);Real-world example A plugin-based application declares 'uses com.example.spi.Plugin' in its own module-info.java, and each separately-developed and deployed plugin module declares 'provides com.example.spi.Plugin with ...', giving the module system explicit, verifiable knowledge of every plugin relationship in the application, rather than relying purely on the older convention-based text file mechanism the module system has no direct visibility into.