Mastering Java and Spring SPI: From Basics to Advanced Implementation
This article explains Java's built‑in Service Provider Interface (SPI) mechanism, demonstrates how to create and load SPI implementations with ServiceLoader, and then shows how Spring extends SPI using spring.factories with detailed code examples and source‑code analysis.
Java SPI (Service Provider Interface) is a built‑in discovery mechanism that enables framework extensions by loading implementations of a given interface from META-INF/services files on the classpath. The article first introduces the core concept and references a previous deep dive.
Java SPI Implementation
The java.util.ServiceLoader class scans the classpath for files named after the fully qualified interface name under META-INF/services and loads the listed implementation classes.
Creating a Dynamic Interface
public interface VedioSPI {
void call();
}Implementation 1
public class Mp3Vedio implements VedioSPI {
@Override
public void call() {
System.out.println("this is mp3 call");
}
}Implementation 2
public class Mp4Vedio implements VedioSPI {
@Override
public void call() {
System.out.println("this is mp4 call");
}
}Place a file named com.skywares.fw.juc.spi.VedioSPI in META-INF/services containing the fully qualified names of the implementations.
Testing the Java SPI
public class VedioSPITest {
public static void main(String[] args) {
ServiceLoader<VedioSPI> loader = ServiceLoader.load(VedioSPI.class);
loader.forEach(VedioSPI::call);
}
}The output shows both implementations being invoked, confirming that ServiceLoader successfully discovers and iterates over the services.
Source Code Analysis of Java SPI
The ServiceLoader class implements Iterable and uses an internal LazyIterator to create iterator instances. All service configuration files reside in the immutable META-INF/services directory.
ServiceLoader’s iterator delegates to LazyIterator for lazy loading.
Each service interface requires a separate configuration file.
Limitations of Java SPI include the need to traverse all services and the mandatory placement of configuration files under META-INF/services.
Spring SPI
Spring adopts the same SPI idea but uses a single spring.factories file to map multiple interfaces to their implementations, enhancing extensibility without modifying Spring’s core.
Defining an Interface
public interface DataBaseSPI {
void getConnection();
}Implementations
// DB2 implementation
public class DB2DataBase implements DataBaseSPI {
@Override
public void getConnection() {
System.out.println("this database is db2");
}
}
// MySQL implementation
public class MysqlDataBase implements DataBaseSPI {
@Override
public void getConnection() {
System.out.println("this is mysql database");
}
}Steps to enable Spring SPI:
Create spring.factories under META-INF.
Add the mapping:
com.skywares.fw.juc.springspi.DataBaseSPI = com.skywares.fw.juc.springspi.DB2DataBase, com.skywares.fw.juc.springspi.MysqlDataBaseMultiple implementations are separated by commas.
Testing Spring SPI
public class SpringSPITest {
public static void main(String[] args) {
List<DataBaseSPI> spis = SpringFactoriesLoader.loadFactories(DataBaseSPI.class, Thread.currentThread().getContextClassLoader());
for (DataBaseSPI spi : spis) {
spi.getConnection();
}
}
}Key differences:
Java SPI: one configuration file per interface, all files under services directory.
Spring SPI: a single spring.factories file holds multiple interface‑implementation mappings, using fully qualified interface names as keys and comma‑separated implementation class names as values.
Spring SPI Source Code Insights
The method loadFactoryNames parses spring.factories to retrieve fully qualified implementation class names. It enumerates all META-INF/spring.factories resources across the classpath, merges entries, and uses reflection to instantiate each class.
Overall, Spring’s SPI builds on Java’s ServiceLoader but simplifies configuration and supports multiple implementations per interface within a single file, addressing some of Java SPI’s drawbacks.
Reference: https://juejin.cn/post/7132742686099898398
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
