Java SPI实现:ServiceLoader 的使用
SPI 释义
在Java中,SPI其实可以理解为一个接口规范,有点类似于你电脑的外设,以鼠标举例。电脑制造商只给你提供一个鼠标的插口,至于鼠标是什么牌子,什么形状,电脑不关心,只要鼠标能够满足接口规范就行了。SPI英文全程 Service Provider Interface,即服务提供的接口,其实就是基于Java接口服务的一种服务扩展机制而已,可以用来替换框架中的扩展和组件,如下图:
SPI 在Java中的实现(tip: 如果不明白实现,直接看使用示例就明白怎么玩了。)
Java 为解决 SPI 问题,在Java4的时候提供了一个服务加载类,即 ServiceLoader。ServiceLoader可以直接加载Jar按规定提供的服务接口实现,具体使用方式如下所示:
- 在类加载路径下,在目录META-INF/services下的文件(以Interface全路径命名)中添加具体实现类的全路径名;
- 接口的实现类放在程序的加载路径下。
- 实现接口实现类,特别注意:实现类必须提供一个无参构造方法。
Java SPI使用示例
1. 定义接口
package com.lm.service;/*** @author Liu.Liangyuan* @version $Id: IService.java, v 0.1 2022年04月10日 8:35 下午 LiangMu Exp $$*/
public interface IService {void sayHello();
}
2. 提供实现类
我们这里提供了接口的2个实现类。
package com.lm.service.impl;import com.lm.service.IService;/*** @author Liu.Liangyuan* @version $Id: CatService.java, v 0.1 2022年04月10日 8:36 下午 LiangMu Exp $$*/
public class CatService implements IService {@Overridepublic void sayHello() {System.out.println("cat hello");}
}
package com.lm.service.impl;import com.lm.service.IService;/*** @author Liu.Liangyuan* @version $Id: DogService.java, v 0.1 2022年04月10日 8:35 下午 LiangMu Exp $$*/
public class DogService implements IService {@Overridepublic void sayHello() {System.out.println("dog hello");}
}
3. 提供ServiceLoader配置
4. 调用ServiceLoader来加载接口服务
package com.lm;import com.lm.service.IService;import java.util.ServiceLoader;/*** @author Liu.Liangyuan* @version $Id: Main.java, v 0.1 2022年04月10日 8:38 下午 LiangMu Exp $$*/
public class Main {public static void main(String[] args) {ServiceLoader<IService> serviceLoader = ServiceLoader.load(IService.class);for (IService service : serviceLoader) {service.sayHello();}}
}
DEBUG
RUN RESULT
Spring框架也提供了SPI的实现方式,这里不赘述,有兴趣的直接百度。
Java SPI实现:ServiceLoader 的使用
SPI 释义
在Java中,SPI其实可以理解为一个接口规范,有点类似于你电脑的外设,以鼠标举例。电脑制造商只给你提供一个鼠标的插口,至于鼠标是什么牌子,什么形状,电脑不关心,只要鼠标能够满足接口规范就行了。SPI英文全程 Service Provider Interface,即服务提供的接口,其实就是基于Java接口服务的一种服务扩展机制而已,可以用来替换框架中的扩展和组件,如下图:
SPI 在Java中的实现(tip: 如果不明白实现,直接看使用示例就明白怎么玩了。)
Java 为解决 SPI 问题,在Java4的时候提供了一个服务加载类,即 ServiceLoader。ServiceLoader可以直接加载Jar按规定提供的服务接口实现,具体使用方式如下所示:
- 在类加载路径下,在目录META-INF/services下的文件(以Interface全路径命名)中添加具体实现类的全路径名;
- 接口的实现类放在程序的加载路径下。
- 实现接口实现类,特别注意:实现类必须提供一个无参构造方法。
Java SPI使用示例
1. 定义接口
package com.lm.service;/*** @author Liu.Liangyuan* @version $Id: IService.java, v 0.1 2022年04月10日 8:35 下午 LiangMu Exp $$*/
public interface IService {void sayHello();
}
2. 提供实现类
我们这里提供了接口的2个实现类。
package com.lm.service.impl;import com.lm.service.IService;/*** @author Liu.Liangyuan* @version $Id: CatService.java, v 0.1 2022年04月10日 8:36 下午 LiangMu Exp $$*/
public class CatService implements IService {@Overridepublic void sayHello() {System.out.println("cat hello");}
}
package com.lm.service.impl;import com.lm.service.IService;/*** @author Liu.Liangyuan* @version $Id: DogService.java, v 0.1 2022年04月10日 8:35 下午 LiangMu Exp $$*/
public class DogService implements IService {@Overridepublic void sayHello() {System.out.println("dog hello");}
}
3. 提供ServiceLoader配置
4. 调用ServiceLoader来加载接口服务
package com.lm;import com.lm.service.IService;import java.util.ServiceLoader;/*** @author Liu.Liangyuan* @version $Id: Main.java, v 0.1 2022年04月10日 8:38 下午 LiangMu Exp $$*/
public class Main {public static void main(String[] args) {ServiceLoader<IService> serviceLoader = ServiceLoader.load(IService.class);for (IService service : serviceLoader) {service.sayHello();}}
}
DEBUG
RUN RESULT
Spring框架也提供了SPI的实现方式,这里不赘述,有兴趣的直接百度。
发布评论