美文网首页
Java SPI机制 、Android组件化跨模块调用

Java SPI机制 、Android组件化跨模块调用

作者: 玉树林枫 | 来源:发表于2022-01-22 10:35 被阅读0次

    1、Java SPI机制 ServiceLoader的基本使用

    • Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制,
      提供了通过interface寻找implement的方法。类似于IOC的思想,将装配的控制权移到程序之外,从而实现解耦。

      Java SPI机制
    • 场景:比如两个module,app依赖basic_live,但这时basic_live又用到了app模块中的服务。
      源码GitHub

    2、方式一

    • 在调用module中创建一个接口文件ContentService
    • 在具体实现的module中的main目录(Java同级)下建立resources/META-INF/services/,因为ServiceLoader中会访问到(查看ServiceLoader.PREFIX)
    • 在services文件夹中创建文件,以接口全名命名
    • 在具体实现的module中创建类来实现接口功能ContentServiceImpl,然后把全类名填到上面创建的文件中

    3、方式二

    • 在方式一中,不仅要创建各种路径、文件,容易写错,所以Google发布了一个库autoservice帮助大家

    • 在具体实现module中添加依赖,kotlin的可以用kpt

    • implementation 'com.google.auto.service:auto-service:1.0.1'
      annotationProcessor 'com.google.auto.service:auto-service:1.0.1'
      
      kapt 'com.google.auto.service:auto-service:1.0.1'
      
    • 实现接口,并加上@AutoService

    • @AutoService(ContentService.class)
      public class ContentServiceImpl implements ContentService {
            @Override
            public String getTitle() {
                 return "the title from app module";
             }
       }
      

    4、使用

    • 在ServiceFactory中加了缓存,通过ContentService service = ServiceFactory.getInstance().getService(ContentService.class)获取

    • public class ServiceFactory {
      
        private static class SingleTonHolder {
            private static final ServiceFactory INSTANCE = new ServiceFactory();
        }
      
        public static ServiceFactory getInstance() {
            return SingleTonHolder.INSTANCE;
        }
        private final ArrayMap<Class, ServiceLoader> loaderMap = new ArrayMap<>();
        private final ArrayMap<Class, Object> serviceMap = new ArrayMap<>();
        private ServiceFactory() {
      
        }
        @Nullable
        public <T> T getService(Class<T> clazz) {
            Object o = serviceMap.get(clazz);
            if (o != null && isInterface(o.getClass(),clazz.getName())) {
                return (T) o;
            }
            ServiceLoader serviceLoader = loaderMap.get(clazz);
            if (serviceLoader == null) {
                serviceLoader = ServiceLoader.load(clazz);
                loaderMap.put(clazz, serviceLoader);
            }
            if (serviceLoader != null && serviceLoader.iterator().hasNext()) {
                T next = (T) serviceLoader.iterator().next();
                serviceMap.put(clazz, next);
                return next;
            }
            return null;
        }
        public boolean isInterface(Class c, String szInterface) {
            Class[] face = c.getInterfaces();
            for (Class aClass : face) {
                if (aClass.getName().equals(szInterface)) {
                    return true;
                } else {
                    Class[] face1 = aClass.getInterfaces();
                    for (Class value : face1) {
                        if (value.getName().equals(szInterface)) {
                            return true;
                        } else if (isInterface(value, szInterface)) {
                            return true;
                        }
                    }
                }
            }
            if (null != c.getSuperclass()) {
                return isInterface(c.getSuperclass(), szInterface);
            }
            return false;
        }
      }
      

    相关文章

      网友评论

          本文标题:Java SPI机制 、Android组件化跨模块调用

          本文链接:https://www.haomeiwen.com/subject/cfjuhrtx.html