【SPI的设计目标】
面向对象的设计里,模块之间是基于接口编程,模块之间不对实现类进行硬编码。
一旦代码里设计具体的实现类,就违法了可插拔的原则,如果需要替代一种实现,就要修改代码。
为了实现在模块装配的时候,不在模块里面写死代码,就需要一种服务发现机制。
Java spi 就是提供了这样一种机制:
为某个接口寻找服务实现的机制。有点类似IOC的思想,就是讲装配的控制权转移到代码之外。
【SPI的具体约定】
当服务的提供者(provider),提供了一个接口多种实现时,
一般会在jar包的META-INF/services目录下,创建该接口的同名文件。
该文件里面的内容就是该服务的具体实现类的名称。
当外部加载这个模块的时候,就能通过该jar包的META-INF/services/里面的配置文件得到具体的实现类名,并加载实例化,完成模块的装配。
【工厂目录结构】
【service相关的接口和类】
package com.jdk.spi.service; /** * Service类 * Created by HigginCui on 2018/9/5. */ public interface AnimalService { void eat(); } package com.jdk.spi.service.impl; import com.jdk.spi.service.AnimalService; /** * Service实现类CatServiceImpl * Created by HigginCui on 2018/9/5. */ public class CatServiceImpl implements AnimalService{ public void eat() { System.out.println("猫爱吃鱼..."); } } package com.jdk.spi.service.impl; import com.jdk.spi.service.AnimalService; /** * Service实现类CatServiceImpl * Created by HigginCui on 2018/9/5. */ public class DogServiceImpl implements AnimalService { public void eat() { System.out.println("狗爱啃骨头..."); } }
【com.jdk.spi.service.AnimalService文件中的内容】
com.jdk.spi.service.impl.DogServiceImpl
【JDKSpiTest类】
package com.jdk.spi; import com.jdk.spi.service.AnimalService; import java.util.ServiceLoader; /** * Created by HigginCui on 2018/9/5. */ public class JdkSpiTest { public static void main(String[] args) { ServiceLoader<AnimalService> loader = ServiceLoader.load(AnimalService.class); for (AnimalService animalService:loader){ animalService.eat(); } } }
【运行结果】
原文地址:https://www.cnblogs.com/HigginCui/p/9589470.html
时间: 2024-10-14 06:28:26