马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
配景
服务注册和查找机制是一种常见的计划模式,它答应我们在运行时动态地加载和使用服务。本文的配景是为了在鸿蒙上实现我们Android版本中的服务注册和查找机制。在Android中我们利用服务注册和查找机制,将基座和第三方SDK的开辟分脱离来,用户可以按照我们给定的框架,自由开辟他们的SDK,再和基座一起打包成APK。基座则基于服务框架,调用第三方SDK的本领。通过这种方式,将基座开辟和第三方SDK的开辟完全解耦。
一、Java中的服务注册和查找
1.1 原理
在Java中,ServiceLoader类提供了一种服务提供者框架,它答应模块化应用程序在运行时动态加载、查找和使用服务提供者。
ServiceLoader是Java的一种服务提供者加载设施,它遵照了服务提供者框架模式(Service Provider Framework Pattern)。这种模式包罗三个组件:服务接口(Service Interface)、提供者注册API(Provider Registration API)、服务访问API(Service Access API)。在Java中,ServiceLoader类就是提供者注册API和服务访问API的实现。
ServiceLoader的工作原理主要基于Java的类路径(Classpath)搜刮和META-INF/services目录。当使用ServiceLoader.load(Class<S> service)方法时,ServiceLoader会搜刮类路径下全部META-INF/services/目录中名为服务接口全限定名的文件。这个文件是一个简单的文本文件,其中每一行都是一个服务提供者类的全限定名。ServiceLoader会读取这个文件,然后使用类加载器(ClassLoader)加载并实例化这些服务提供者类。
这种机制答应服务提供者在运行时被发现和加载,而无需在编译时进行硬编码,从而提供了很好的模块化和解耦。
1.2 例子
以下是一个简单的例子:
- public interface IService {
- void doSomething();
- }
复制代码- public class MyService implements IService {
- public void doSomething() {
- System.out.println("Doing something...");
- }
- }
复制代码
- 在META-INF/services/目录下创建一个名为com.example.IService的文件(全限定名),文件内容是MyService的全限定名:
- ServiceLoader<IService> services = ServiceLoader.load(IService.class);
- for (IService service : services) {
- service.doSomething();
- }
复制代码 在这个例子中,当我们运行上述代码时,ServiceLoader会自动找到并加载MyService,然后调用其doSomething方法。
二、鸿蒙中使用TypeScript实现的服务注册和查找
2.1 使用反射和配置文件模拟Java中的SeviceLoader
2.1.1 SDK侧
- export interface IService {
- doSomething(): void;
- }
复制代码- export class MyService implements IService {
- doSomething(): void {
- console.log("Doing something...");
- }
- }
复制代码- export interface IServiceRegister {
- registerService(): Array<IService>;
- }
复制代码- export class MyServiceRegister implements IServiceRegister {
- registerService(): Array<IService> {
- // 返回一个IService的实例数组
- return [new MyService(), new MyService()];
- }
- }
复制代码
- 在lib_third_library的Index.ets中暴露接口和服务注册实现类:
- export { IService, IServiceRegister } from './src/main/ets/third_library/MyServiceRegister'
- export { MyServiceRegister } from './src/main/ets/third_library/MyServiceRegister'
复制代码 2.1.2 基座侧
- interface ClassData {
- className: string[];
- }
- import('lib_third_library').then((ns: any) => {
- let fileName = 'meta.json';
- let res = $rawfile(fileName);
- // 读取文件内容并转换为字符串
- let jsonString = bytes2Str(ResUtil.getResManagerByResource(res).getRawFileContentSync(fileName));
- // 将字符串解析为 JSON 对象,并将其类型断言为 ClassData
- let classData = JSON.parse(jsonString) as ClassData;
- classData.className.forEach((className) => {
- console.log(className);
- let registerServiceFunctionName = 'registerService';
- // 使用类名实例化类
- let myServiceRegisterImpl: any = new ns[className]();
- // 调用 registerService 方法并获取返回的列表,列表中的每个元素都是 IService 类型
- let serviceList: IService[] = myServiceRegisterImpl[registerServiceFunctionName]();
- serviceList.forEach((service: IService) => {
- // 运行服务函数
- service.doSomething();
- });
- });
- });
复制代码- {
- "className":["MyServiceRegister"]
- }
复制代码 在这个例子中,我们首先创建了一个 MyServiceRegister 来注册全部的服务。然后,我们从 MyServiceRegister 中获取 MyService,并调用其 doSomething 方法。
2.2 关键技能点
- meta.json是为了模拟java的META-INF/services/目录,必要SDK实现方写好实现类的名字:
- {
- "className":["MyServiceRegister"]
- }
复制代码
- 通过反射,调用第三方SDK中的服务注册类的注册函数,模拟java中的SeviceLoader.load。
- registerService 注册服务的函数名字固定不变
- registerService返回的是service的数组
- let registerServiceFunctionName = 'registerService';
- // 使用类名实例化类
- let myServiceRegisterImpl: any = new ns[className]();
- // 调用 registerService 方法并获取返回的列表,列表中的每个元素都是 IService 类型
- let serviceList: IService[] = myServiceRegisterImpl[registerServiceFunctionName]();
复制代码 三、优缺点分析
Java和TypeScript中的服务注册和查找机制都有其各自的优缺点:
标准化易用性延长加载服务生命周期管理解耦支持类型检查灵活度Java是,Java的ServiceLoader是Java平台的一部分,全部的Java开辟者都可以使用它,无需额外的库或框架。必要在META-INF/services/目录下创建配置文件,而且必要手动输入服务提供者的全限定名,这可能会导致错误。是,ServiceLoader支持延长加载,只有在真正必要服务提供者时,才会加载和实例化它们。无法管理服务提供者的生命周期,比方,无法控礼服务提供者的创建和销毁。是,通过使用ServiceLoader,服务的使用者和提供者可以完全解耦,它们只必要知道服务接口,而无需知道具体的实现。不支持,Java在编译时并不会检查服务的类型,可能会在运行时出现类型错误。较低,Java的ServiceLoader机制相对固定,不易进行定制。TypeScript否,TypeScript没有标准的服务注册和查找机制,不同的项目可能会有不同的实现。必要实现接口并注册服务,创建一份自定义的配置文件。否,TypeScript的服务注册和查找机制无法实现服务的延长加载。TypeScript的服务注册和查找机制通常无法管理服务的生命周期,除非在服务注册表中添加额外的逻辑。是,通过使用服务注册表,服务的使用者和提供者可以完全解耦,它们只必要知道服务接口,而无需知道具体的实现。是,由于TypeScript支持静态类型检查,因此可以在编译时检查服务的类型,避免了运行时类型错误。较高,TypeScript的服务注册和查找机制更加灵活,可以根据必要自定义服务注册表。 Java和TypeScript中的服务注册和查找机制各有优缺点,选择哪种机制取决于具体的需求和场景。
四、结论
Java的ServiceLoader提供了一种动态的、松耦合的服务加载机制,适合构建模块化的、可扩展的应用程序。本文在鸿蒙上模拟Java的ServiceLoader的机制,给出了一种可以在大型工程中解耦第三方SDK的鸿蒙实现,希望能给读者一些思绪启发。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |