转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/125859181
本文出自【赵彦军的博客】

文章目录

  • SPI
  • 总结
  • auto-service
  • 总结
  • 识别多个服务
  • 实例作用域问题
  • SPA应用实战1 —— 子模块如何获取主模块的BuildConfig信息
  • Auto Service 源码

SPI

SPI(Service Provider Interface)是 Java 提供的一种动态服务发现机制。通过SPI 机制,我们可以直接跨模块查找到想要的接口实现类,从而避免不必要的模块间依赖,降低模块之间的耦合性。

Java 内置的 SPI 机制是通过 ServiceLoader 查找某个接口的所有实现类,并实例化。

每个需要实例化模块下需要以该接口的全限定名(包名+类名)为文件名放到 resources/META-INF/services/ 目录下,然后将他的实现类的全限定名按行依次写到该文件中。

1、创建接口类 StudentInterface

public interface StudentInterface {void eat(String name);
}

2、创建接口实现类 StudentImpl

package com.zyj.demo;import android.util.Log;public class StudentImpl implements StudentInterface {@Overridepublic void eat(String name) {Log.d("yu--", "" + name);}
}

StudentImpl 类的全路径为 : com.zyj.demo.StudentImpl

3、创建目录

  • main 目录下,创建 resources 目录
  • resources 目录下,创建 META-INF 目录
  • META-INF 目录下,创建 service 目录

service 目录下,创建 com.zyj.demo.StudentInterface 文件

文件的内容为:com.zyj.demo.StudentImpl


4、ServiceLoader 发现服务

接口可以有多个实现类,所以返回值是一个集合

//发现服务,接口可以有多个实现类,所以返回值是一个集合
ServiceLoader<StudentInterface> serviceLoader = ServiceLoader.load(StudentInterface.class);//遍历服务
for (StudentInterface impl : serviceLoader) {impl.eat("zyj");
}

总结

  • 动态服务发现机制,可以很好的解耦,不必直接依赖接口实现类。
  • ServiceLoader.load 每次都会创建一个新对象。生命周期用完即销毁
  • 缺点也很明显,要手动往 resources/META-INF/services/ 写入文件。

有没有一种自动写入的工具,可以解放双手?

有的,下面我们就介绍 auto-service

auto-service

auto-service 是 google 出品的自动发现服务工具 ,是 SPA 的一种方式。

  • SPA :Service Pool for Android

依赖:

 annotationProcessor 'com.google.auto.service:auto-service:1.0'mplementation 'com.google.auto.service:auto-service-annotations:1.0'

我们只需要在 接口的实现类上,加上 @AutoService 注解,就可以了。

@AutoService(StudentInterface.class)
public class StudentImpl implements StudentInterface {@Overridepublic void eat(String name) {Log.d("yu--", "" + name);}
}

发现服务,还是需要 ServiceLoader.load ,这个跟 Java 使用的是一致的。

//发现服务,接口可以有多个实现类,所以返回值是一个集合
ServiceLoader<StudentInterface> serviceLoader = ServiceLoader.load(StudentInterface.class);//遍历服务
for (StudentInterface impl : serviceLoader) {impl.eat("zyj");
}

总结

auto-service 的优势是,自动的往 resources/META-INF/services/ 写入文件,解放了双手,666666

我们看一眼这个目录,在 build 目录可以看到

识别多个服务

由于接口可以有多个实现类,所以我们通过 ServiceLoader.load(StudentInterface.class); 有可能有多个实例,我们如何区分自己需要的哪一个。

impl.getClass().getSimpleName() 可以获取实现类的名字。如下:

    void test() {ServiceLoader<StudentInterface> serviceLoader = ServiceLoader.load(StudentInterface.class, StudentInterface.class.getClassLoader());for (StudentInterface impl : serviceLoader) {if (impl.getClass().getSimpleName().equals("StudentImpl")) {//这就是我们的需要的服务impl.eat("zyj");}}}

实例作用域问题

即使用了 auto-service ,也不能解决实例作用域问题,如果需要全局使用,就需要自己实现单例了,这里不再展开。

SPA应用实战1 —— 子模块如何获取主模块的BuildConfig信息

多模块开发/组件化开发过程中,主模块(plugin为com.android.application的模块,一般指app模块)可以依赖任何模块,但是子模块无法依赖主模块,如果子模块想拿主模块的内容要怎么办呢? 下面演示如何通过Spa来获取主模块的Context和BuildConfig中的内容。

先在接口层定义一个BuildService

public interface BuildService {String buglyId(); // build.gradle中使用buildConfigField定义的buglyIdboolean debuggable();String versionName();int versionCode();String applicationId();String buildType();
}

在app模块中,实现这个service接口并使用 @AutoService 标记

BuildServiceImpl.java

@AutoService(BuildService.class)
public class BuildServiceImpl implements BuildService {@Overridepublic String buglyId() {return BuildConfig.BUGLY_ID;}@Overridepublic boolean debuggable() {return BuildConfig.DEBUG;}@Overridepublic String versionName() {return BuildConfig.VERSION_NAME;}@Overridepublic int versionCode() {return BuildConfig.VERSION_CODE;}@Overridepublic String applicationId() {return BuildConfig.APPLICATION_ID;}@Overridepublic String buildType() {return BuildConfig.BUILD_TYPE;}
}

准备工作已经完成,现在我们在pages模块的BuildInfoActivity中应用它

public class BuildInfoActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);BuildInfoPageBinding viewBinding = BuildInfoPageBinding.inflate(LayoutInflater.from(this));setContentView(viewBinding.getRoot());BuildService buildService = Spa.getService(BuildService.class);viewBinding.applicationId.setText("applicationId: " + buildService.applicationId());viewBinding.versionName.setText("versionName: " + buildService.versionName());viewBinding.versionCode.setText("versionCode: " + buildService.versionCode() + "");viewBinding.buildType.setText("buildType: " + buildService.buildType());viewBinding.debuggable.setText("debuggable: " + buildService.debuggable());viewBinding.buglyId.setText("buglyId:" + buildService.buglyId());}
}}

Auto Service 源码

https://github.com/google/auto/tree/master/service

Android 服务动态发现 SPA 之 Auto Service相关推荐

  1. consul集群搭建,配合nginx完成服务动态发现和健康检查

    1.概述 1.1 介绍 consul是一个服务发现和配置共享的服务软件,结合nginx的主动健康检查模块nginx_upstream_check_module和服务发现模块nginx-upsync-m ...

  2. WS-Discovery(网络服务动态发现)协议再解读

    WS-Discovery(网络服务动态发现)协议再解读 文章目录 WS-Discovery(网络服务动态发现)协议再解读 1.概述 2.协议资料 3.协议介绍 (1).适用范围 (2).不适用 4.协 ...

  3. android服务启动失败Unable to start service Intent U=0: not found

    android启动服务失败,提示:Unable to start service Intent { cmp=xxx/.xxx} U=0: not found.检查清单文件服务配置没有错,启动服务的方法 ...

  4. Android 服务类Service 的详细学习

    http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建 目录(?)[+] 什么是服务 服务有什么 ...

  5. android服务常驻内存,android service常驻内存的一点思考

    我们总是不想自己的Android service被系统清理,以前时候大家最常用的办法就是在JNI里面fork出子进程,然后监视 service进程状态,被系统杀死了就重启它. 我分别在android4 ...

  6. android服务常用在哪里,第十七章 Android 常见的Service

    1. 引言 现实生活中的服务很常见,各式各样的人都在从事服务这个行业.但是Android中的服务呢?Android中的服务在哪里?我们什么时候需要服务呢?Android 中的服务怎么用?这就是这篇文章 ...

  7. Android服务之Service(其一)

    转载地址:http://www.cnblogs.com/zhangdongzi/archive/2012/01/08/2316711.html android中服务是运行在后台的东西,级别与activ ...

  8. android服务的启动过程,Android Service的启动过程(上)

    原标题:Android Service的启动过程(上) (点击上方公众号,可快速关注) 来源:伯乐在线专栏作者 - xuyinhuan 链接:http://android.jobbole.com/85 ...

  9. android 服务是什么问题,Android Studio 中的Service问题

    新手,在学习Service一开始就碰到了问题 是根据教程做的,在开启服务时闪退 MyService.java package com.example.administrator.myhhhhh; im ...

最新文章

  1. OSPF 提升 一 ----基础
  2. 单链表倒数第K个节点的查找和显示
  3. python选出奇数并降序_奇数结点升序偶数结点降序的单链表排序(Python实现)
  4. 内存泄漏 和 内存溢出
  5. 袁亚湘:愿为数学做更多
  6. Python高级编程(三)
  7. Windows phone 开发基础(14) WP8磁贴分两种的创建方式(内建和外建)
  8. JWT(JSON Web Token) 多网站的单点登录,放弃session 转载https://www.cnblogs.com/lexiaofei/p/7409846.html...
  9. (1)数据结构-绪论
  10. [小说连载]张小庆,在路上(2)- 兰博和威震天
  11. openwrt刷回原厂固件_小米路由器4刷breed, pandavan,openwrt
  12. aoa计算机二级考试答案操作题,浙江省计算机二级等级考试aoa理论题.pdf
  13. QT + OpenCV 使用摄像头
  14. android 播放gif会闪,android 播放gif动图
  15. 中介者模式:还记得你到单位入职的第一天吗?你有没有遇到文中‘王二’的事呢?
  16. Excel成神之道-001-数据分列
  17. winrar 命令解压缩
  18. oracle 11g duplicate database基于备份复制数据库(六)
  19. 高考读卡机是谁发明的?
  20. 用好销冠话术库,业绩增长十倍

热门文章

  1. 统一文档服务器,统一标准化文档oraclei服务器安装基础手册.doc
  2. 小红书X千瓜联合发布|小红书2021年4月创作者红人榜
  3. 一种基于Android、iOS平台的移动端车牌识别方法,能够在复杂背景下迅速识别多种车牌
  4. 将excel中的一个工作表按照某列拆分成多个sheet工作表
  5. 那些我们对2019技术世界趋势的预测都说准了吗?
  6. 电子爱好者都应该至少有一台示波器
  7. SQL Server 阻止保存要求重新创建表的更改
  8. 汽车价格离群值检测案例
  9. 吴恩达-目标检测讲解笔记
  10. 桔子菌和楼下超市田大爷的角色互换经历–Python做的商品价格语音播报器