Android Gradle插件平台开发系列一:Android APT
Android Gradle插件平台开发系列二:Android SPI
Android Gradle插件平台开发系列三:自定义gradle plugin
Android Gralde插件平台开发系列四:自定义Gradle Transform
一、定义
SPI全称Service Provider Interface,服务提供者接口,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。通俗点来说,SPI就是一种服务发现机制,为接口寻找其实现类。
1.1 SPI机制
(1)定义一个接口
(2)写出多个该接口的实现
(3)使用 @AutoService 注册实现类
(4)使用ServiceLoader来获取这些实现类
1.2. SPI的优点
只提供服务接口,具体服务由其他组件实现,接口和具体实现分离,同时能够通过系统的ServiceLoader拿到这些实现类的集合,统一处理。
1.3. SPI的缺点
不能按需加载,且ServiceLoader内部通过反射实例化对象,存在一定性能开销。
1.4. 优化思路
ServiceLoader读取SPI配置信息是在程序运行时,我们可以将这个读取配置信息的动作提前,在编译时候就搞定,通过gradle插件,去扫描class文件,找到具体的服务类,然后生成新的java文件,这个文件中包含了具体的实现类。
二、作用
实现模块解耦,面向接口编程,在不修改核心代码的情况下,实现功能扩展。
三、实现流程
这里以APP组件化中的模块初始化场景作为示例。
3.1 在base层定义初始化接口
ModuleBase:
public interface IAppInit {
void init(Application application);
}
3.2 在各业务module中实现初始化逻辑
ModuleA:
@AutoService(IAppInit.class)
public class ModuleAInit implements IAppInit {
@Override
public void init(Application application) {
System.out.println("init-->ModuleAInit");
}
}
ModuleB:
@AutoService(IAppInit.class)
public class ModuleBInit implements IAppInit {
@Override
public void init(Application application) {
System.out.println("init-->ModuleBInit");
}
}
ModuleC:
@AutoService(IAppInit.class)
public class ModuleCInit implements IAppInit {
@Override
public void init(Application application) {
System.out.println("init-->ModuleCInit ");
}
}
3.3 在主module的自定义Application中加载各模块初始化逻辑
private void init() {
ServiceLoader<IAppInit> serviceLoader = ServiceLoader.load(IAppInit.class);
Iterator<IAppInit> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
iterator.next().init(getApplication());
}
}
3.4 总结
综上所述,我们只需在base层定义一个IAppInit接口,然后把具体的初始化逻辑放在各module中,各module只需负责自己的初始化逻辑,由主module统一加载,这样就实现了业务隔离,不管后面是增加还是减少module都对主流程没有影响,真正实现了非侵入式编程。
当然这个示例只是为了能更加形象地理解SPI的定义和作用,在实际开发过程中并不建议这么使用,因为ServiceLoader内部是通过反射来实例化对象的,当IAppInit接口有比较多的实现类时,ServiceLoader统一加载的时候可能会存在一定的性能开销,需要根据实际情况做取舍。
四、怎么解决SPI的性能问题
滴滴Booster的大佬johnsonlee已经给出了解决方案,可以参考他的SPI 性能优化方案。
参考
https://www.it610.com/article/1490069257126436864.htm
https://blog.csdn.net/xiaohanluo/article/details/71515678
https://www.jianshu.com/p/c65a307223c9