Android Gradle插件平台开发系列二:Android SPI

Android Gradle插件平台开发系列:前言

Android Gradle插件平台开发系列一:Android APT

Android Gradle插件平台开发系列二:Android SPI

Android Gradle插件平台开发系列三:自定义gradle plugin

Android Gralde插件平台开发系列四:自定义Gradle Transform

Android Gralde插件平台开发系列五:字节码修改

一、定义

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值