
JDK 1.8
SPI(Service Provider Interface): 服务提供接口,是JDK提供的一种服务加载机制,简单理解就是通过此JDK规范可实现服务的发现并加载。主要有三部分组成: Service: 服务,更准确来说是服务定义,可以接口、抽象类,同样可以是普通的类(服务提供者为其子类,不过一般不这么来定义) Service Provider: 服务提供者,可以是Service接口实现类,Service抽象类的实现,以及Service类的继承 ServiceLoader: 一个简单的服务提供者加载工具
原始的参考资料可参考JDK源码中对java.util.ServiceLoader的描述。


面向接口编程、接口隔离原则(ISP)


package cn.com.demo.api;
public interface ISpiDemo {
String name();
String exec(String msg);
}package cn.com.demo.api;
public abstract class AnstractSpiDemo {
public abstract String sayHello();
}package cn.com.demo.api;
public class SpiDemo {
public String sayHello(){
return this.getClass().getSimpleName();
}
}cn.com.demo.impl.Hello0ISpiDemo
package cn.com.demo.impl;
import cn.com.demo.api.ISpiDemo;
public class Hello0ISpiDemo implements ISpiDemo {
@Override
public String name() {
return this.getClass().getSimpleName();
}
@Override
public String exec(String msg) {
return name()+msg;
}
}cn.com.demo.impl.Hello1ISpiDemo
package cn.com.demo.impl;
import cn.com.demo.api.ISpiDemo;
public class Hello1ISpiDemo implements ISpiDemo {
@Override
public String name() {
return this.getClass().getSimpleName();
}
@Override
public String exec(String msg) {
return name()+msg;
}
}cn.com.demo.impl.Hello2ISpiDemo
package cn.com.demo.impl;
import cn.com.demo.api.ISpiDemo;
public class Hello2ISpiDemo implements ISpiDemo {
@Override
public String name() {
return this.getClass().getSimpleName();
}
@Override
public String exec(String msg) {
return name()+msg;
}
}META-INF/services/下定义 文件名:cn.com.demo.api.ISpiDemo 文件内容:
cn.com.demo.impl.Hello1ISpiDemo
cn.com.demo.impl.Hello2ISpiDemo
注意: 这里的cn.com.demo.impl.Hello0ISpiDemo未被定义到services文件中,应用将不会注册此类。
cn.com.demo.impl.AnstractSpiDemoImpl
package cn.com.demo.impl;
import cn.com.demo.api.AnstractSpiDemo;
public class AnstractSpiDemoImpl extends AnstractSpiDemo {
@Override
public String sayHello() {
return this.getClass().getSimpleName();
}
}META-INF/services/下定义 文件名:cn.com.demo.api.AnstractSpiDemo 文件内容:
cn.com.demo.impl.AnstractSpiDemoImpl
cn.com.demo.impl.SpiDemoChild
package cn.com.demo.impl;
import cn.com.demo.api.SpiDemo;
public class SpiDemoChild extends SpiDemo {
@Override
public String sayHello() {
return this.getClass().getSimpleName();
}
}META-INF/services/下定义 文件名:cn.com.demo.api.SpiDemo 文件内容:
cn.com.demo.impl.SpiDemoChild
cn.com.demo.app.SpiTest
package cn.com.demo.app;
import cn.com.demo.api.ISpiDemo;
import cn.com.demo.api.SpiDemo;
import cn.com.demo.api.AnstractSpiDemo;
import lombok.extern.java.Log;
import java.util.ServiceLoader;
@Log
public class SpiTest {
public static void main(String[] args) {
ServiceLoader<ISpiDemo> load = ServiceLoader.load(ISpiDemo.class);
for (ISpiDemo spiDemo : load) {
log.info(spiDemo.name()+"-"+spiDemo);
}
log.info("------------------------------");
ServiceLoader<AnstractSpiDemo> loader = ServiceLoader.load(AnstractSpiDemo.class);
for (AnstractSpiDemo spiDemoC : loader) {
log.info(spiDemoC.sayHello());
}
log.info("------------------------------");
ServiceLoader<SpiDemo> loader1 = ServiceLoader.load(SpiDemo.class);
for (SpiDemo spiDemo : loader1) {
log.info(spiDemo.sayHello());
}
}
}