SPI-Service Provider Interface

其实就是别人提供了一个类,读取指定目录下的文件,通过反射方式创建对象。

为什么来说spi?因为spring boot就是通过spi来创建对象的。

首先写一个接口:

public interface TestInterface {
    void test();
}

写几个实现类:

public class TestClass1 implements TestInterface {

    @Override
    public void test() {
        System.out.println("TestClass1");
    }
    public TestClass1(){
        System.out.println("构造器:TestClass1");
    }
}
public class TestClass2 implements TestInterface {

    @Override
    public void test() {
        System.out.println("TestClass2");
    }
    public TestClass2(){
        System.out.println("构造器:TestClass2");
    }
}
public class TestClass3 implements TestInterface {

    @Override
    public void test() {
        System.out.println("TestClass3");
    }
    public TestClass3(){
        System.out.println("构造器:TestClass3");
    }
}

要使用spi,必须遵守其规范,要求在根目录下新建META-INF/services,

新建文件,文件名与接口全类名一致,这里为com.sunsas.spi.TestInterface

内容为其实现类全类名:

com.sunsas.spi.TestClass1
com.sunsas.spi.TestClass2
com.sunsas.spi.TestClass3

编写测试类:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import sun.misc.Service;

import java.util.Iterator;
import java.util.ServiceLoader;

@SpringBootTest
class SpiApplicationTests {

    @Test
    void test() {
        ServiceLoader<TestInterface> load = ServiceLoader.load(TestInterface.class);
        Iterator<TestInterface> iterator = load.iterator();
        while(iterator.hasNext()){
            TestInterface next = iterator.next();
            next.test();
        }
        System.out.println("----------------------------------");
        // 下面这种方式也可以
        Iterator<TestInterface> providers = Service.providers(TestInterface.class);
        while(providers.hasNext()){
            TestInterface next = providers.next();
            next.test();
        }
    }
}

两者输出结果一致:

构造器:TestClass1
TestClass1
构造器:TestClass2
TestClass2
构造器:TestClass3
TestClass3
原文地址:https://www.cnblogs.com/SunSAS/p/12263688.html