Introduction to the use of SPI

Posted by Joe Haley on Sat, 16 Nov 2019 21:05:53 +0100

spi is the abbreviation of Service Provider Interface. Using spi technology, we can change the implementation class of an interface in a program by modifying the configuration, so as to change the program behavior. The usage of spi is as follows:

  1. Define the interface.
package com.foo.bar.service;
public interface Foo {
    String foo(String name);
}

  1. Write the interface implementation class.
package com.foo.provider.v1;
public class FooServiceProvider implements Foo {
    String foo(String name) {
        return "hello" + name;
    }
}

package com.foo.provider.v2;
public class FooServiceProvider implements Foo {
    String foo(String name) {
        return String.format("Hello, %s!", name);
    }
}

  1. Establish the spi file.

Create a file META-INF\services\com.foo.bar.service.FooService and write the following two lines:

com.foo.bar.provider.v1.FooServiceProvider
com.foo.bar.provider.v2.FooServiceProvider

  1. Load the interface implementation class.
import java.util.ServiceLoader;
import com.foo.bar.service.FooService;

public class App {
  public static void main(String[] args) {
  for (FooService provider: ServiceLoader.load(FooService.class)) {
    System.out.println(provider.foo("Foo");
  }
}

  1. Use spi in Spring.
public interface BarService {
  public String bar(String abc);
}

public class BarServiceProvider {
  public String bar(String abc) { return ""; }
}

public class Demo {
  private static ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfiguration.class);

  public static void main(String[] args) {
    BarService dictionary = ctx.getBean(BarService.class);
    System.out.println("Book: " + dictionary.bar("book"));
  }
}

@Configuration
public class AppConfiguration {  
  @Bean
  public BarService barService(ServiceLoader<Service> loader) {
    return new Service(loader);
  }

  @Bean
  public ServiceLoaderFactoryBean dictionaryServiceLoaderFactory() {
    ServiceLoaderFactoryBean factoryBean = new ServiceLoaderFactoryBean();
    factoryBean.setServiceType(BarService.class);
    return factoryBean;
  }
}

  1. Use spi for JDBC.

Edit the file META-INF/services/java.sql.Driver to add the required driver class.

Reference material

Topics: Programming Java Spring JDBC SQL