Android模块化注入服务

439 阅读15分钟

模块化开发中,模块之间跨模块进行服务调用,获取其他服务的功能是一种常见的现象。

image.png

例如,模块A、B、C分别提供了Service A、B、C,模块A、B、C均依赖于base模块,然后再base模块里面定义了Service A、B、C各自实现的接口InterfaceA、B、C。此时模块A想要调用模块B的Service,因为模块A、B间相互不依赖,所以需要通过base模块中提供的InterfaceB来进行服务的获取。怎么通过InterfaceB获取到ServiceB的实例,进而使用其提供的服务呢?

我们可以知道,因为各个模块最终都会打包到主工程中,如果我们知道要使用的服务的全限定类名,就可以通过反射来实例化具体对象。但是这样初始化一个实例需要保证被实例化的那个服务类保持不变,而且获得的对象是一个新的实例,如果各个模块对于服务有各自的初始化逻辑,或者业务过程中有不同的配置,那这样的服务是不能满足需求的。

如果可以根据base模块中的Interface作为key获取到对应模块中的Service,然后调用具体的功能就好了。这样子就不需要依赖反射提供的全限定类名来实例化,也可以获取经过配置的服务实例。

答案就是APT。

首先定义一个需要被APT识别的注解。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 声明一个ServiceLoader,通过interface和key加载实现类。此注解可以用在任意静态类上。
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface IServiceLoader {

    /**
     * 实现的接口(或继承的父类)
     */
    Class[] interfaces();

    /**
     * 同一个接口的多个实现类之间,可以通过唯一的key区分。
     */
    String[] key() default {};

    /**
     * 是否为单例。如果是单例,则使用ServiceLoader.getService不会重复创建实例。
     */
    boolean singleton() default false;

    /**
     * 是否设置为默认实现类。如果是默认实现类,则在获取该实现类实例时可以不指定key
     */
    boolean defaultImpl() default false;
}

然后通过解析器解析具有这个注解的Service。


import com.google.auto.service.AutoService;
import com.sun.tools.javac.code.Symbol;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.MirroredTypesException;
import javax.lang.model.type.TypeMirror;

//核心的注解处理类,在这里我们可以扫描源代码里所有的注解,找到我们需要的注解,然后做出相应处理
@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class ServiceAnnotationProcessor extends BaseProcessor {

    /**
     * interfaceClass --> Entity7
     */
    private final HashMap<String, Entity> mEntityMap = new HashMap<>();
    private String mHash = null;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
        if (env.processingOver()) {
            generateInitClass();//实例化注解类
        } else {
            processAnnotations(env);//解析注解
        }
        return true;
    }

    private void processAnnotations(RoundEnvironment env) {
        for (Element element : env.getElementsAnnotatedWith(IServiceLoader.class)) {
            if (!(element instanceof Symbol.ClassSymbol)) {
                continue;
            }

            Symbol.ClassSymbol cls = (Symbol.ClassSymbol) element;
            if (mHash == null) {
                mHash = hash(cls.className());
            }

            IServiceLoader service = cls.getAnnotation(IServiceLoader.class);
            if (service == null) {
                continue;
            }

            List<? extends TypeMirror> typeMirrors = getInterface(service);
            String[] keys = service.key();

            String implementationName = cls.className();
            boolean singleton = service.singleton();
            final boolean defaultImpl = service.defaultImpl();

            if (typeMirrors != null && !typeMirrors.isEmpty()) {
                for (TypeMirror mirror : typeMirrors) {
                    if (mirror == null) {
                        continue;
                    }
                    if (!isConcreteSubType(cls, mirror)) {
                        String msg = cls.className() + "没有实现注解" + IServiceLoader.class.getName()
                                + "标注的接口" + mirror.toString();
                        throw new RuntimeException(msg);
                    }
                    String interfaceName = getClassName(mirror);

                    Entity entity = mEntityMap.get(interfaceName);
                    if (entity == null) {
                        entity = new Entity(interfaceName);
                        mEntityMap.put(interfaceName, entity);
                    }

                    if (defaultImpl) {
                        //如果设置为默认实现,则手动添加一个内部标识默认实现的key
                        entity.put(ServiceImpl.DEFAULT_IMPL_KEY, implementationName, singleton);
                    }

                    if (keys.length > 0) {
                        for (String key : keys) {
                            if (key.contains(":")) {
                                String msg = String.format("%s: 注解%s的key参数不可包含冒号",
                                        implementationName, IServiceLoader.class.getName());
                                throw new RuntimeException(msg);
                            }
                            entity.put(key, implementationName, singleton);
                        }
                    } else {
                        entity.put(null, implementationName, singleton);
                    }
                }
            }
        }
    }

    private void generateInitClass() {
        if (mEntityMap.isEmpty() || mHash == null) {
            return;
        }
        ServiceInitClassBuilder generator = new ServiceInitClassBuilder("ServiceInit" + Const.SPLITTER + mHash);
        for (Map.Entry<String, Entity> entry : mEntityMap.entrySet()) {
            for (ServiceImpl service : entry.getValue().getMap().values()) {
                generator.put(entry.getKey(), service.getKey(), service.getImplementation(), service.isSingleton());
            }
        }
        generator.build();
    }

    private static List<? extends TypeMirror> getInterface(IServiceLoader service) {
        try {
            service.interfaces();
        } catch (MirroredTypesException mte) {
            return mte.getTypeMirrors();
        }
        return null;
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return new HashSet<>(Collections.singletonList(IServiceLoader.class.getName()));
    }

    public static class Entity {

        private final String mInterfaceName;

        private final Map<String, ServiceImpl> mMap = new HashMap<>();

        public Entity(String interfaceName) {
            mInterfaceName = interfaceName;
        }

        public Map<String, ServiceImpl> getMap() {
            return mMap;
        }

        public void put(String key, String implementationName, boolean singleton) {
            if (implementationName == null) {
                return;
            }
            ServiceImpl impl = new ServiceImpl(key, implementationName, singleton);
            ServiceImpl prev = mMap.put(impl.getKey(), impl);
            String errorMsg = ServiceImpl.checkConflict(mInterfaceName, prev, impl);
            if (errorMsg != null) {
                throw new RuntimeException(errorMsg);
            }
        }

        public List<String> getContents() {
            List<String> list = new ArrayList<>();
            for (ServiceImpl impl : mMap.values()) {
                list.add(impl.toConfig());
            }
            return list;
        }
    }
}
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;

import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

public abstract class BaseProcessor extends AbstractProcessor {

    protected Filer filer;
    protected Types types;
    protected Elements elements;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        filer = processingEnvironment.getFiler();
        types = processingEnvironment.getTypeUtils();
        elements = processingEnvironment.getElementUtils();
    }

    /**
     * 从字符串获取TypeElement对象
     */
    public TypeElement typeElement(String className) {
        return elements.getTypeElement(className);
    }

    /**
     * 从字符串获取TypeMirror对象
     */
    public TypeMirror typeMirror(String className) {
        return typeElement(className).asType();
    }

    /**
     * 从字符串获取ClassName对象
     */
    public ClassName className(String className) {
        return ClassName.get(typeElement(className));
    }

    /**
     * 从字符串获取TypeName对象,包含Class的泛型信息
     */
    public TypeName typeName(String className) {
        return TypeName.get(typeMirror(className));
    }

    public static String getClassName(TypeMirror typeMirror) {
        return typeMirror == null ? "" : typeMirror.toString();
    }

    public boolean isSubType(TypeMirror type, String className) {
        return type != null && types.isSubtype(type, typeMirror(className));
    }

    public boolean isSubType(Element element, String className) {
        return element != null && isSubType(element.asType(), className);
    }

    public boolean isSubType(Element element, TypeMirror typeMirror) {
        return element != null && types.isSubtype(element.asType(), typeMirror);
    }

    /**
     * 非抽象类
     */
    public boolean isConcreteType(Element element) {
        return element instanceof TypeElement && !element.getModifiers().contains(
                Modifier.ABSTRACT);
    }

    /**
     * 非抽象子类
     */
    public boolean isConcreteSubType(Element element, String className) {
        return isConcreteType(element) && isSubType(element, className);
    }

    /**
     * 非抽象子类
     */
    public boolean isConcreteSubType(Element element, TypeMirror typeMirror) {
        return isConcreteType(element) && isSubType(element, typeMirror);
    }

    public boolean isInterceptor(Element element) {
        return isConcreteSubType(element, Const.URI_INTERCEPTOR_CLASS);
    }

    public static String randomHash() {
        return hash(UUID.randomUUID().toString());
    }

    public static String hash(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            return new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            return Integer.toHexString(str.hashCode());
        }
    }

    /**
     * 创建Handler。格式:<code>"com.demo.TestActivity"</code> 或 <code>new TestHandler()</code>
     */
    public CodeBlock buildHandler(boolean isActivity, Symbol.ClassSymbol cls) {
        CodeBlock.Builder b = CodeBlock.builder();
        if (isActivity) {
            b.add("$S", cls.className());
        } else {
            b.add("new $T()", cls);
        }
        return b.build();
    }

    /**
     * 创建Interceptors。格式:<code>, new Interceptor1(), new Interceptor2()</code>
     */
    public CodeBlock buildInterceptors(List<? extends TypeMirror> interceptors) {
        CodeBlock.Builder b = CodeBlock.builder();
        if (interceptors != null && interceptors.size() > 0) {
            for (TypeMirror type : interceptors) {
                if (type instanceof Type.ClassType) {
                    Symbol.TypeSymbol e = ((Type.ClassType) type).asElement();
                    if (e instanceof Symbol.ClassSymbol && isInterceptor(e)) {
                        b.add(", new $T()", e);
                    }
                }
            }
        }
        return b.build();
    }

    /**
     * 生成类似下面格式的HandlerInitClass,同时生成ServiceInitClass
     * <pre>
     * package com.sankuai.waimai.router.generated;
     * public class UriRouter_RouterUri_xxx implements IUriAnnotationInit {
     *     public void init(UriAnnotationHandler handler) {
     *         handler.register("", "", "/login", "com.xxx.LoginActivity", false);
     *         // ...
     *     }
     * }
     * </pre>
     *
     * @param code             方法中的代码
     * @param genClassName     生成class的SimpleClassName,形如 UriRouter_RouterUri_xxx
     * @param handlerClassName Handler类名,例如 com.sankuai.waimai.router.common.UriAnnotationHandler
     * @param interfaceName    接口名,例如 com.sankuai.waimai.router.common.IUriAnnotationInit
     */
    public void buildHandlerInitClass(CodeBlock code, String genClassName, String handlerClassName, String interfaceName) {
        MethodSpec methodSpec = MethodSpec.methodBuilder(Const.INIT_METHOD)
                .addModifiers(Modifier.PUBLIC)
                .returns(TypeName.VOID)
                .addParameter(className(handlerClassName), "handler")
                .addCode(code)
                .build();
        TypeSpec typeSpec = TypeSpec.classBuilder(genClassName)
                .addSuperinterface(className(interfaceName))
                .addModifiers(Modifier.PUBLIC)
                .addMethod(methodSpec)
                .build();
        try {
            JavaFile.builder(Const.GEN_PKG, typeSpec)
                    .build()
                    .writeTo(filer);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        String fullImplName = Const.GEN_PKG + Const.DOT + genClassName;
        String className = "ServiceInit" + Const.SPLITTER + hash(genClassName);

        new ServiceInitClassBuilder(className)
                .putDirectly(interfaceName, fullImplName, fullImplName, false)
                .build();
    }

    /**
     * 辅助工具类,用于生成ServiceInitClass,格式如下:
     * <pre>
     * package com.midea.base.serviceloader.api.generated.service;
     *
     * import com.midea.base.serviceloader.api.service.ServiceLoader;
     *
     * public class &lt;ClassName&gt; {
     *     public static void init() {
     *         ServiceLoader.put(com.xxx.interface1.class, "key1", com.xxx.implementsA.class, false);
     *         ServiceLoader.put(com.xxx.interface2.class, "key2", com.xxx.implementsB.class, false);
     *     }
     * }
     * </pre>
     */
    public class ServiceInitClassBuilder {

        private final String className;
        private final CodeBlock.Builder builder;
        private final ClassName serviceLoaderClass;

        public ServiceInitClassBuilder(String className) {
            this.className = className;
            this.builder = CodeBlock.builder();
            this.serviceLoaderClass = className(Const.SERVICE_LOADER_CLASS);
        }

        public ServiceInitClassBuilder put(String interfaceName, String key, String implementName, boolean singleton) {
            builder.addStatement("$T.put($T.class, $S, $T.class, $L)",
                    serviceLoaderClass,
                    className(interfaceName),
                    key,
                    className(implementName),
                    singleton);
            return this;
        }

        public ServiceInitClassBuilder putDirectly(String interfaceName, String key, String implementName, boolean singleton) {
            // implementName是注解生成的类,直接用$L拼接原始字符串
            builder.addStatement("$T.put($T.class, $S, $L.class, $L)",
                    serviceLoaderClass,
                    className(interfaceName),
                    key,
                    implementName,
                    singleton);
            return this;
        }

        public void build() {
            MethodSpec methodSpec = MethodSpec.methodBuilder(Const.INIT_METHOD)
                    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                    .returns(TypeName.VOID)
                    .addCode(this.builder.build())
                    .build();

            TypeSpec typeSpec = TypeSpec.classBuilder(this.className)
                    .addModifiers(Modifier.PUBLIC)
                    .addMethod(methodSpec)
                    .build();
            try {
                JavaFile.builder(Const.GEN_PKG_SERVICE, typeSpec)
                        .build()
                        .writeTo(filer);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
public class Const {

    private static final String PKG = "com.zpw.base.core.serviceloader.api.";

    public static final String NAME = "MIDEA_BASE";

    // 生成的代码
    public static final String GEN_PKG = PKG + "generated";
    public static final String GEN_PKG_SERVICE = GEN_PKG + ".service";
    public static final String SPLITTER = "_";

    /**
     * ServiceLoader初始化
     */
    public static final String SERVICE_LOADER_INIT = GEN_PKG + ".ServiceLoaderInit";
    public static final char DOT = '.';
    public static final String INIT_METHOD = "init";

    public static final String URI_INTERCEPTOR_CLASS = PKG + "core.UriInterceptor";
    public static final String SERVICE_LOADER_CLASS = PKG + "service.ServiceLoader";
}

通过APT解析注解之后,我们会生成如下Java文件。可见这个实现类将Interface和对应的服务实现类保存了起来。

package com.zpw.base.core.serviceloader.api.generated.service;

import com.example.myapplication.ConfigMoaService;
import com.example.myapplication.IConfigMoa;
import com.midea.base.core.serviceloader.api.service.ServiceLoader;

public class ServiceInit_a8270c82eb44fbd3083fd91dd2fce7ef {
  public static void init() {
    ServiceLoader.put(IConfigMoa.class, "com.example.myapplication.ConfigMoaService", ConfigMoaService.class, true);
    ServiceLoader.put(IConfigMoa.class, "_service_default_impl", ConfigMoaService.class, true);
  }
}

这里面的SeviceLoader其实是一个容器。


import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.midea.base.core.serviceloader.annotation.interfaces.Const;
import com.midea.base.core.serviceloader.annotation.service.ServiceImpl;
import com.midea.base.core.serviceloader.api.components.RouterComponents;
import com.midea.base.core.serviceloader.api.core.Debugger;
import com.midea.base.core.serviceloader.api.utils.LazyInitHelper;
import com.midea.base.core.serviceloader.api.utils.SingletonPool;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 通过接口Class获取实现类
 * @param <I> 接口类型
 */
public class ServiceLoader<I> {

    private static final Map<Class, ServiceLoader> SERVICES = new HashMap<>();

    private static final LazyInitHelper sInitHelper = new LazyInitHelper("ServiceLoader") {
        @Override
        protected void doInit() {
            try {
                // 反射调用Init类,避免引用的类过多,导致main dex capacity exceeded问题
                Class.forName(Const.SERVICE_LOADER_INIT)
                        .getMethod(Const.INIT_METHOD)
                        .invoke(null);
                Debugger.i("[ServiceLoader] init class invoked");
            } catch (Exception e) {
                Debugger.fatal(e);
            }
        }
    };

    /**
     * @see LazyInitHelper#lazyInit()
     */
    public static void lazyInit() {
        sInitHelper.lazyInit();
    }

    /**
     * 提供给InitClass使用的初始化接口
     *
     * @param interfaceClass 接口类
     * @param implementClass 实现类
     */
    public static void put(Class interfaceClass, String key, Class implementClass, boolean singleton) {
        ServiceLoader loader = SERVICES.get(interfaceClass);
        if (loader == null) {
            loader = new ServiceLoader(interfaceClass);
            SERVICES.put(interfaceClass, loader);
        }
        loader.putImpl(key, implementClass, singleton);
    }

    /**
     * 根据接口获取 {@link ServiceLoader}
     */
    @SuppressWarnings("unchecked")
    public static <T> ServiceLoader<T> load(Class<T> interfaceClass) {
        sInitHelper.ensureInit();
        if (interfaceClass == null) {
            Debugger.fatal(new NullPointerException("ServiceLoader.load的class参数不应为空"));
            return EmptyServiceLoader.INSTANCE;
        }
        ServiceLoader service = SERVICES.get(interfaceClass);
        if (service == null) {
            synchronized (SERVICES) {
                service = SERVICES.get(interfaceClass);
                if (service == null) {
                    service = new ServiceLoader(interfaceClass);
                    SERVICES.put(interfaceClass, service);
                }
            }
        }
        return service;
    }

    /**
     * key --> class name
     */
    private HashMap<String, ServiceImpl> mMap = new HashMap<>();

    private final String mInterfaceName;

    private ServiceLoader(Class interfaceClass) {
        if (interfaceClass == null) {
            mInterfaceName = "";
        } else {
            mInterfaceName = interfaceClass.getName();
        }
    }

    private void putImpl(String key, Class implementClass, boolean singleton) {
        if (key != null && implementClass != null) {
            mMap.put(key, new ServiceImpl(key, implementClass, singleton));
        }
    }

    /**
     * 创建指定key的实现类实例,使用 {@link IServiceProvider} 方法或无参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回null
     */
    public <T extends I> T get(String key) {
        return createInstance(mMap.get(key), null);
    }

    /**
     * 创建指定key的实现类实例,使用Context参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回null
     */
    public <T extends I> T get(String key, Context context) {
        return createInstance(mMap.get(key), new ContextFactory(context));
    }

    /**
     * 创建指定key的实现类实例,使用指定的Factory构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回null
     */
    public <T extends I> T get(String key, IFactory factory) {
        return createInstance(mMap.get(key), factory);
    }

    /**
     * 创建所有实现类的实例,使用 {@link IServiceProvider} 方法或无参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    @NonNull
    public <T extends I> List<T> getAll() {
        return getAll((IFactory) null);
    }

    /**
     * 创建所有实现类的实例,使用Context参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    @NonNull
    public <T extends I> List<T> getAll(Context context) {
        return getAll(new ContextFactory(context));
    }

    /**
     * 创建所有实现类的实例,使用指定Factory构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    @NonNull
    public <T extends I> List<T> getAll(IFactory factory) {
        Collection<ServiceImpl> services = mMap.values();
        if (services.isEmpty()) {
            return Collections.emptyList();
        }
        List<T> list = new ArrayList<>(services.size());
        for (ServiceImpl impl : services) {
            T instance = createInstance(impl, factory);
            if (instance != null) {
                list.add(instance);
            }
        }
        return list;
    }

    /**
     * 获取指定key的实现类。注意,对于声明了singleton的实现类,获取Class后还是可以创建新的实例。
     *
     * @return 可能返回null
     */
    @SuppressWarnings("unchecked")
    public <T extends I> Class<T> getClass(String key) {
        return (Class<T>) mMap.get(key).getImplementationClazz();
    }

    /**
     * 获取所有实现类的Class。注意,对于声明了singleton的实现类,获取Class后还是可以创建新的实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    @SuppressWarnings("unchecked")
    @NonNull
    public <T extends I> List<Class<T>> getAllClasses() {
        List<Class<T>> list = new ArrayList<>(mMap.size());
        for (ServiceImpl impl : mMap.values()) {
            Class<T> clazz = (Class<T>) impl.getImplementationClazz();
            if (clazz != null) {
                list.add(clazz);
            }
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    @Nullable
    private <T extends I> T createInstance(@Nullable ServiceImpl impl, @Nullable IFactory factory) {
        if (impl == null) {
            return null;
        }
        Class<T> clazz = (Class<T>) impl.getImplementationClazz();
        if (impl.isSingleton()) {
            try {
                return SingletonPool.get(clazz, factory);
            } catch (Exception e) {
                Debugger.fatal(e);
            }
        } else {
            try {
                if (factory == null) {
                    factory = RouterComponents.getDefaultFactory();
                }
                T t = factory.create(clazz);
                Debugger.i("[ServiceLoader] create instance: %s, result = %s", clazz, t);
                return t;
            } catch (Exception e) {
                Debugger.fatal(e);
            }
        }
        return null;
    }

    @Override
    public String toString() {
        return "ServiceLoader (" + mInterfaceName + ")";
    }

    public static class EmptyServiceLoader extends ServiceLoader {

        public static final ServiceLoader INSTANCE = new EmptyServiceLoader();

        public EmptyServiceLoader() {
            super(null);
        }

        @NonNull
        @Override
        public List<Class> getAllClasses() {
            return Collections.emptyList();
        }

        @NonNull
        @Override
        public List getAll() {
            return Collections.emptyList();
        }

        @NonNull
        @Override
        public List getAll(IFactory factory) {
            return Collections.emptyList();
        }

        @Override
        public String toString() {
            return "EmptyServiceLoader";
        }
    }
}

这里面用ServiceImpl封装了服务对应的参数。

import java.util.Objects;

/**
 * Service的一个实现
 */
public class ServiceImpl {

    private static final String SPLITTER = ":";
    private static final String SINGLETON = "singleton";
    public static final String DEFAULT_IMPL_KEY = "_service_default_impl";

    public static String checkConflict(String interfaceName, ServiceImpl impl, ServiceImpl previous) {
        if (impl != null && previous != null && !stringEquals(previous.implementation, impl.implementation)) {
            if (DEFAULT_IMPL_KEY.equals(impl.getKey())) {
                return String.format("接口%s 的默认实现只允许存在一个\n目前存在多个默认实现: %s, %s", interfaceName, previous, impl);
            } else {
                return String.format("接口%s对应key='%s'存在多个实现: %s, %s", interfaceName, impl.getKey(), previous, impl);
            }
        }
        return null;
    }

    private static boolean stringEquals(String s1, String s2) {
        return Objects.equals(s1, s2);
    }

    private static boolean isEmpty(String key) {
        return key == null || key.length() == 0;
    }

    private final String key;
    private final String implementation;
    private final Class implementationClazz;
    private final boolean singleton;

    public ServiceImpl(String key, Class implementation, boolean singleton) {
        if (key == null || implementation == null) {
            throw new RuntimeException("key和implementation不应该为空");
        }
        this.key = key;
        this.implementation = "";
        this.implementationClazz = implementation;
        this.singleton = singleton;
    }

    public ServiceImpl(String key, String implementation, boolean singleton) {
        if (isEmpty(implementation)) {
            throw new RuntimeException("implementation不应该为空");
        }
        this.key = isEmpty(key) ? implementation : key; // 没有指定key,则为implementation
        this.implementation = implementation;
        this.implementationClazz = null;
        this.singleton = singleton;
    }

    public String toConfig() {
        String s = key + SPLITTER + implementation;
        if (singleton) {
            s += SPLITTER + SINGLETON;
        }
        return s;
    }

    /**
     * not null
     */
    public String getKey() {
        return key;
    }

    public String getImplementation() {
        return implementation;
    }

    public Class getImplementationClazz() {
        return implementationClazz;
    }

    public boolean isSingleton() {
        return singleton;
    }

    @Override
    public String toString() {
        return implementation;
    }
}

实例化服务类的工厂。


import androidx.annotation.NonNull;

import com.midea.base.core.serviceloader.api.service.DefaultFactory;
import com.midea.base.core.serviceloader.api.service.IFactory;

/**
 * 用于配置组件
 */
public class RouterComponents {

    @NonNull
    private static IFactory sDefaultFactory = DefaultFactory.INSTANCE;


    public static void setDefaultFactory(IFactory factory) {
        sDefaultFactory = factory == null ? DefaultFactory.INSTANCE : factory;
    }

    @NonNull
    public static IFactory getDefaultFactory() {
        return sDefaultFactory;
    }
}
import androidx.annotation.NonNull;

import com.midea.base.core.serviceloader.api.utils.ProviderPool;

/**
 * 默认的Factory,先尝试Provider,再尝试无参数构造
 */

public class DefaultFactory implements IFactory {

    public static final DefaultFactory INSTANCE = new DefaultFactory();

    private DefaultFactory() {

    }

    @NonNull
    @Override
    public <T> T create(@NonNull Class<T> clazz) throws Exception {
        T t = ProviderPool.create(clazz);
        if (t != null) {
            return t;
        } else {
            return clazz.newInstance();
        }
    }
}
import androidx.annotation.NonNull;

/**
 * 从Class构造实例
 */
public interface IFactory {

    @NonNull
    <T> T create(@NonNull Class<T> clazz) throws Exception;
}

初始化工具类。

import android.os.SystemClock;

import com.midea.base.core.serviceloader.api.core.Debugger;

/**
 * 初始化辅助工具类。
 *
 * 一些初始化任务可以在使用时按需初始化(通常在主线程);
 * 但也可以提前调用并初始化(通常在后台线程),使用时等待初始化完成。
 */
public abstract class LazyInitHelper {

    private final String mTag;
    private boolean mHasInit = false;

    public LazyInitHelper(String tag) {
        mTag = tag;
    }

    /**
     * 此初始化方法的调用不是必须的。
     * 使用时会按需初始化;但也可以提前调用并初始化,使用时会等待初始化完成。
     * 本方法线程安全。
     */
    public void lazyInit() {
        performInit();
    }

    /**
     * 使用时确保已经初始化;如果正在初始化,则等待完成。
     */
    public void ensureInit() {
        performInit();
    }

    private void performInit() {
        if (!mHasInit) {
            synchronized (this) {
                if (!mHasInit) {
                    long ts = 0;
                    final boolean enableLog = Debugger.isEnableLog();
                    if (enableLog) {
                        ts = SystemClock.uptimeMillis();
                    }
                    try {
                        doInit();
                        mHasInit = true;
                    } catch (Throwable t) {
                        Debugger.fatal(t);
                    }
                    if (enableLog) {
                        Debugger.i("%s init cost %s ms", mTag,
                                SystemClock.uptimeMillis() - ts);
                    }
                }
            }
        }
    }

    protected abstract void doInit();
}

单例缓存。

package com.midea.base.core.serviceloader.api.utils;


import androidx.annotation.NonNull;

import com.midea.base.core.serviceloader.api.service.IFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 单例缓存
 */
public class SingletonPool {

    private static final Map<Class, Object> CACHE = new HashMap<>();

    @SuppressWarnings("unchecked")
    public static <I, T extends I> T get(Class<I> clazz, IFactory factory) throws Exception {
        if (clazz == null) {
            return null;
        }
        if (factory == null) {
            factory = RouterComponents.getDefaultFactory();
        }
        Object instance = getInstance(clazz, factory);
        Debugger.i("[SingletonPool]   get instance of class = %s, result = %s", clazz, instance);
        return (T) instance;
    }

    @NonNull
    private static Object getInstance(@NonNull Class clazz, @NonNull IFactory factory) throws Exception {
        Object t = CACHE.get(clazz);
        if (t != null) {
            return t;
        } else {
            synchronized (CACHE) {
                t = CACHE.get(clazz);
                if (t == null) {
                    Debugger.i("[SingletonPool] >>> create instance: %s", clazz);
                    t = factory.create(clazz);
                    //noinspection ConstantConditions
                    if (t != null) {
                        CACHE.put(clazz, t);
                    }
                }
            }
            return t;
        }
    }
}

通过上面的APT操作,我们将各个模块需要提供给外界使用的Service都保存起来了,这时候需要将它们汇总并初始化。这时候需要使用Tramsform。使用插件来执行最后的逻辑。

import com.android.build.gradle.BaseExtension;

import org.gradle.api.Plugin;
import org.gradle.api.Project;

/**
 * 插件所做工作:将注解生成器生成的初始化类汇总到ServiceLoaderInit,运行时直接调用ServiceLoaderInit
 */
public class ServiceLoaderPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {
        WMRouterExtension extension = project.getExtensions().create(Const.NAME, WMRouterExtension.class);

        WMRouterLogger.info("register transform");
        project.getExtensions().findByType(BaseExtension.class).registerTransform(new WMRouterTransform());

        project.afterEvaluate(p -> WMRouterLogger.setConfig(extension));
    }
}
public class WMRouterExtension {

    /**
     * 出错时中断编译
     */
    private boolean abortOnError = true;
    /**
     * 是否允许Log
     */
    private boolean enableLog = true;
    /**
     * 是否开启Debug。Debug模式会输出更详细的Log。
     */
    private boolean enableDebug = false;

    public void setAbortOnError(boolean abortOnError) {
        this.abortOnError = abortOnError;
    }

    public boolean getAbortOnError() {
        return abortOnError;
    }

    public void setEnableLog(boolean enableLog) {
        this.enableLog = enableLog;
    }

    public boolean getEnableLog() {
        return enableLog;
    }

    public void setEnableDebug(boolean enableDebug) {
        this.enableDebug = enableDebug;
    }

    public boolean getEnableDebug() {
        return enableDebug;
    }
}
public class WMRouterLogger {

    private static final String PREFIX = "[SERVICE_LOADER_PLUGIN] ";

    private static boolean sEnableLog = false;
    private static boolean sEnableDebug = false;
    private static boolean sAbortOnError = false;

    public static void setConfig(WMRouterExtension extension) {
        sEnableDebug = extension.getEnableDebug();
        sEnableLog = extension.getEnableLog() || extension.getEnableDebug();
        sAbortOnError = extension.getAbortOnError();
    }

    public static void debug(String s, Object... args) {
        if (sEnableDebug) {
            System.out.println(format(s, args));
        }
    }

    public static void info(String s, Object... args) {
        if (sEnableLog) {
            System.out.println(format(s, args));
        }
    }

    public static void warn(String s, Object... args) {
        if (sEnableLog) {
            System.err.println(format(s, args));
        }
    }

    public static void error(String s, Object... args) {
        if (sEnableLog) {
            System.err.println(format(s, args));
        }
    }

    public static void error(Throwable t) {
        if (sEnableLog) {
            t.printStackTrace();
        }
    }

    public static void fatal(Throwable t) {
        if (sAbortOnError) {
            if (t instanceof RuntimeException) {
                throw ((RuntimeException) t);
            } else {
                throw new RuntimeException(t);
            }
        } else {
            t.printStackTrace();
        }
    }

    public static void fatal(String s, Object... args) {
        fatal(new RuntimeException(format(s, args)));
    }

    private static String format(String s, Object... args) {
        return PREFIX + (args.length == 0 ? s : String.format(s, args));
    }
}
package com.midea.base.core.serviceloader.plugin;

import com.android.SdkConstants;
import com.android.build.api.transform.Format;
import com.android.build.api.transform.QualifiedContent;
import com.android.build.api.transform.Transform;
import com.android.build.api.transform.TransformInput;
import com.android.build.api.transform.TransformInvocation;
import com.android.build.gradle.internal.pipeline.TransformManager;
import com.google.common.collect.ImmutableSet;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOCase;
import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;


public class WMRouterTransform extends Transform {

    private static final String TRANSFORM = "Transform: ";
    private static final String GENERATE_INIT = "GenerateInit: ";

    /**
     * Linux/Unix: com/sankuai/waimai/router/generated/service
     * Windows:    com\sankuai\waimai\router\generated\service
     */
    public static final String INIT_SERVICE_DIR = Const.GEN_PKG_SERVICE.replace('.', File.separatorChar);
    /**
     * com/sankuai/waimai/router/generated/service
     */
    public static final String INIT_SERVICE_PATH = Const.GEN_PKG_SERVICE.replace('.', '/');

    @Override
    public String getName() {
        return Const.NAME;
    }

    @Override
    public Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS;
    }

    @Override
    public Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT;
    }

    @Override
    public boolean isIncremental() {
        return true;
    }

    @Override
    public void transform(TransformInvocation invocation) {
        WMRouterLogger.info(TRANSFORM + "start...");
        long ms = System.currentTimeMillis();

        Set<String> initClasses = Collections.newSetFromMap(new ConcurrentHashMap<>());

        for (TransformInput input : invocation.getInputs()) {
            input.getJarInputs().parallelStream().forEach(jarInput -> {
                File src = jarInput.getFile();
                File dst = invocation.getOutputProvider().getContentLocation(
                        jarInput.getName(), jarInput.getContentTypes(), jarInput.getScopes(),
                        Format.JAR);
                try {
                    scanJarFile(src, initClasses);
                    FileUtils.copyFile(src, dst);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            input.getDirectoryInputs().parallelStream().forEach(directoryInput -> {
                File src = directoryInput.getFile();
                File dst = invocation.getOutputProvider().getContentLocation(
                        directoryInput.getName(), directoryInput.getContentTypes(),
                        directoryInput.getScopes(), Format.DIRECTORY);
                try {
                    scanDir(src, initClasses);
                    FileUtils.copyDirectory(src, dst);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
        File dest = invocation.getOutputProvider().getContentLocation(
                "WMRouter", TransformManager.CONTENT_CLASS,
                ImmutableSet.of(QualifiedContent.Scope.PROJECT), Format.DIRECTORY);
        generateServiceInitClass(dest.getAbsolutePath(), initClasses);

        WMRouterLogger.info(TRANSFORM + "cost %s ms", System.currentTimeMillis() - ms);
    }

    /**
     * 扫描由注解生成器生成到包 {@link Const#GEN_PKG_SERVICE} 里的初始化类
     */
    private void scanJarFile(File file, Set<String> initClasses) throws IOException {
        JarFile jarFile = new JarFile(file);
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry entry = entries.nextElement();
            String name = entry.getName();
            if (name.endsWith(SdkConstants.DOT_CLASS) && name.startsWith(INIT_SERVICE_PATH)) {
                String className = trimName(name, 0).replace('/', '.');
                initClasses.add(className);
                WMRouterLogger.info("    find ServiceInitClass: %s", className);
            }
        }
    }

    /**
     * 扫描由注解生成器生成到包 {@link Const#GEN_PKG_SERVICE} 里的初始化类
     */
    private void scanDir(File dir, Set<String> initClasses) throws IOException {
        File packageDir = new File(dir, INIT_SERVICE_DIR);
        if (packageDir.exists() && packageDir.isDirectory()) {
            Collection<File> files = FileUtils.listFiles(packageDir,
                    new SuffixFileFilter(SdkConstants.DOT_CLASS, IOCase.INSENSITIVE), TrueFileFilter.INSTANCE);
            for (File f : files) {
                String className = trimName(f.getAbsolutePath(), dir.getAbsolutePath().length() + 1)
                        .replace(File.separatorChar, '.');
                initClasses.add(className);
                WMRouterLogger.info("    find ServiceInitClass: %s", className);
            }
        }
    }

    /**
     * [prefix]com/xxx/aaa.class --> com/xxx/aaa
     * [prefix]com\xxx\aaa.class --> com\xxx\aaa
     */
    private String trimName(String s, int start) {
        return s.substring(start, s.length() - SdkConstants.DOT_CLASS.length());
    }

    /**
     * 生成格式如下的代码,其中ServiceInit_xxx由注解生成器生成。
     * <pre>
     * package com.sankuai.waimai.router.generated;
     *
     * public class ServiceLoaderInit {
     *
     *     public static void init() {
     *         ServiceInit_xxx1.init();
     *         ServiceInit_xxx2.init();
     *     }
     * }
     * </pre>
     */
    private void generateServiceInitClass(String directory, Set<String> classes) {

        if (classes.isEmpty()) {
            WMRouterLogger.info(GENERATE_INIT + "skipped, no service found");
            return;
        }

        try {
            WMRouterLogger.info(GENERATE_INIT + "start...");
            long ms = System.currentTimeMillis();

            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
            ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, writer) {
            };
            String className = Const.SERVICE_LOADER_INIT.replace('.', '/');
            cv.visit(50, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);

            MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
                    Const.INIT_METHOD, "()V", null, null);

            mv.visitCode();

            for (String clazz : classes) {
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, clazz.replace('.', '/'),
                        "init",
                        "()V",
                        false);
            }
            mv.visitMaxs(0, 0);
            mv.visitInsn(Opcodes.RETURN);
            mv.visitEnd();
            cv.visitEnd();

            File dest = new File(directory, className + SdkConstants.DOT_CLASS);
            dest.getParentFile().mkdirs();
            new FileOutputStream(dest).write(writer.toByteArray());

            WMRouterLogger.info(GENERATE_INIT + "cost %s ms", System.currentTimeMillis() - ms);

        } catch (IOException e) {
            WMRouterLogger.fatal(e);
        }
    }
}

通过Tramsfrom会生成一下文件。

package com.midea.base.core.serviceloader.api.generated;

import com.midea.base.core.serviceloader.api.generated.service.ServiceInit_a8270c82eb44fbd3083fd91dd2fce7ef;

public class ServiceLoaderInit {
    public static void init() {
        ServiceInit_a8270c82eb44fbd3083fd91dd2fce7ef.init();
    }
}

然后我们向外界提供一个服务获取类。

import android.content.Context;
import android.os.Looper;
import android.util.Log;

import com.midea.base.core.serviceloader.annotation.IServiceLoader;
import com.midea.base.core.serviceloader.annotation.IServiceProvider;
import com.midea.base.core.serviceloader.annotation.service.ServiceImpl;
import com.midea.base.core.serviceloader.api.core.Debugger;
import com.midea.base.core.serviceloader.api.exception.DefaultServiceException;
import com.midea.base.core.serviceloader.api.method.Func0;
import com.midea.base.core.serviceloader.api.method.Func1;
import com.midea.base.core.serviceloader.api.method.Func2;
import com.midea.base.core.serviceloader.api.method.Func3;
import com.midea.base.core.serviceloader.api.method.Func4;
import com.midea.base.core.serviceloader.api.method.Func5;
import com.midea.base.core.serviceloader.api.method.Func6;
import com.midea.base.core.serviceloader.api.method.Func7;
import com.midea.base.core.serviceloader.api.method.Func8;
import com.midea.base.core.serviceloader.api.method.Func9;
import com.midea.base.core.serviceloader.api.method.FuncN;
import com.midea.base.core.serviceloader.api.service.IFactory;
import com.midea.base.core.serviceloader.api.service.ServiceLoader;

import java.util.List;

/**
 * - utils:通用工具类<br/>
 * - components: 辅助组件<br/>
 * - service: ServiceLoader模块<br/>
 * - method:方法通用接口<br/>
 */
public class ServiceLoaderHelper {

    /**
     * 此初始化方法必须在主线程调用。
     */
    public static void init() {
        if (!Debugger.isLogSetting()) {
            Log.w(Debugger.LOG_TAG, "!!当前未设置Logger,建议通过 Debugger.setLogger()方法设置Logger");
            Log.w(Debugger.LOG_TAG, "!!并在测试环境通过 Debugger.EnableLog(true)方法开启日志");
            Log.w(Debugger.LOG_TAG, "!!通过Debugger.setEnableDebug(true)方法在测试环境及时抛出严重类型异常");
        }
        if (Looper.myLooper() != Looper.getMainLooper()) {
            Debugger.fatal("初始化方法init应该在主线程调用");
        }
    }

    /**
     * 此初始化方法的调用不是必须的。
     * 使用时会按需初始化;但也可以提前调用并初始化,使用时会等待初始化完成。
     * 本方法线程安全。
     */
    public static void lazyInit() {
        ServiceLoader.lazyInit();
    }

    /**
     * 根据接口获取 {@link ServiceLoader}
     */
    public static <T> ServiceLoader<T> loadService(Class<T> clazz) {
        return ServiceLoader.load(clazz);
    }

    /**
     * 创建 指定的clazz的默认实现类的实例,如果没有任何一个实现类指定了{@link IServiceLoader#defaultImpl()},
     * 则会判断 指定的clazz的实现类是否只有一个,如果只有一个则会使用该实现类构造
     * 如果发现有多个 指定的clazz的实现类,则会抛出异常
     *
     * @return 找不到或获取、构造失败,则返回null
     */
    public static <I, T extends I> I getService(Class<I> clazz) {
        final I service = ServiceLoader.load(clazz).get(ServiceImpl.DEFAULT_IMPL_KEY);
        if (service != null) {
            return service;
        } else {
            final List<I> services = getAllServices(clazz);
            if (services.size() == 1) {
                return services.get(0);
            } else if (services.size() > 1) {
                Debugger.fatal(DefaultServiceException.foundMoreThanOneImpl(clazz));
            }
        }
        return null;
    }

    /**
     * 创建 指定的clazz的默认实现类的实例,使用context参数构造,如果没有任何一个实现类指定了{@link IServiceLoader#defaultImpl()},
     * 则会判断 指定的clazz的实现类是否只有一个,如果只有一个则会使用该实现类构造
     * 如果发现有多个 指定的clazz的实现类,则会抛出异常
     *
     * @return 找不到或获取、构造失败,则返回null
     */
    public static <I, T extends I> I getService(Class<I> clazz, Context context) {
        final I service = ServiceLoader.load(clazz).get(ServiceImpl.DEFAULT_IMPL_KEY, context);
        if (service != null) {
            return service;
        } else {
            final List<I> services = getAllServices(clazz, context);
            if (services.size() == 1) {
                return services.get(0);
            } else if (services.size() > 1) {
                Debugger.fatal(DefaultServiceException.foundMoreThanOneImpl(clazz));
            }
        }
        return null;
    }

    /**
     * 创建 指定的clazz的默认实现类的实例,使用指定的Factory构造,如果没有任何一个实现类指定了{@link IServiceLoader#defaultImpl()},
     * 则会判断 指定的clazz的实现类是否只有一个,如果只有一个则会使用该实现类构造
     * 如果发现有多个 指定的clazz的实现类,则会抛出异常
     *
     * @return 找不到或获取、构造失败,则返回null
     */
    public static <I, T extends I> I getService(Class<I> clazz, IFactory factory) {
        final I service = ServiceLoader.load(clazz).get(ServiceImpl.DEFAULT_IMPL_KEY, factory);
        if (service != null) {
            return service;
        } else {
            final List<I> services = getAllServices(clazz, factory);
            if (services.size() == 1) {
                return services.get(0);
            } else if (services.size() > 1) {
                Debugger.fatal(DefaultServiceException.foundMoreThanOneImpl(clazz));
            }
        }
        return null;
    }


    /**
     * 创建指定key的实现类实例,使用 {@link IServiceProvider} 方法或无参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 找不到或获取、构造失败,则返回null
     */
    public static <I, T extends I> T getService(Class<I> clazz, String key) {
        return ServiceLoader.load(clazz).get(key);
    }

    /**
     * 创建指定key的实现类实例,使用Context参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 找不到或获取、构造失败,则返回null
     */
    public static <I, T extends I> T getService(Class<I> clazz, String key, Context context) {
        return ServiceLoader.load(clazz).get(key, context);
    }

    /**
     * 创建指定key的实现类实例,使用指定的Factory构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @param factory 用于从Class构造实例
     * @return 找不到或获取、构造失败,则返回null
     */
    public static <I, T extends I> T getService(Class<I> clazz, String key, IFactory factory) {
        return ServiceLoader.load(clazz).get(key, factory);
    }

    /**
     * 创建所有实现类的实例,使用 {@link IServiceProvider} 方法或无参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    public static <I, T extends I> List<T> getAllServices(Class<I> clazz) {
        return ServiceLoader.load(clazz).getAll();
    }

    /**
     * 创建所有实现类的实例,使用Context参数构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    public static <I, T extends I> List<T> getAllServices(Class<I> clazz, Context context) {
        return ServiceLoader.load(clazz).getAll(context);
    }

    /**
     * 创建所有实现类的实例,使用指定Factory构造。对于声明了singleton的实现类,不会重复创建实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    public static <I, T extends I> List<T> getAllServices(Class<I> clazz, IFactory factory) {
        return ServiceLoader.load(clazz).getAll(factory);
    }

    /**
     * 根据key获取实现类的Class。注意,对于声明了singleton的实现类,获取Class后还是可以创建新的实例。
     *
     * @return 找不到或获取失败,则返回null
     */
    public static <I, T extends I> Class<T> getServiceClass(Class<I> clazz, String key) {
        return ServiceLoader.load(clazz).getClass(key);
    }

    /**
     * 获取所有实现类的Class。注意,对于声明了singleton的实现类,获取Class后还是可以创建新的实例。
     *
     * @return 可能返回EmptyList,List中的元素不为空
     */
    public static <I, T extends I> List<Class<T>> getAllServiceClasses(Class<I> clazz) {
        return ServiceLoader.load(clazz).getAllClasses();
    }

    /**
     * 调用方法。方法应该实现 {@link Func0} ~ {@link FuncN} 接口,根据参数个数匹配接口。
     */
    @SuppressWarnings("unchecked")
    public static <T> T callMethod(String key, Object... args) {
        switch (args.length) {
            case 0:
                return (T) getService(Func0.class, key).call();
            case 1:
                return (T) getService(Func1.class, key).call(args[0]);
            case 2:
                return (T) getService(Func2.class, key).call(args[0], args[1]);
            case 3:
                return (T) getService(Func3.class, key).call(args[0], args[1], args[2]);
            case 4:
                return (T) getService(Func4.class, key).call(
                        args[0], args[1], args[2], args[3]);
            case 5:
                return (T) getService(Func5.class, key).call(
                        args[0], args[1], args[2], args[3], args[4]);
            case 6:
                return (T) getService(Func6.class, key).call(
                        args[0], args[1], args[2], args[3], args[4], args[5]);
            case 7:
                return (T) getService(Func7.class, key).call(
                        args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
            case 8:
                return (T) getService(Func8.class, key).call(
                        args[0], args[1], args[2], args[3],
                        args[4], args[5], args[6], args[7]);
            case 9:
                return (T) getService(Func9.class, key).call(
                        args[0], args[1], args[2], args[3],
                        args[4], args[5], args[6], args[7], args[8]);
            default:
                return (T) getService(FuncN.class, key).call(args);
        }
    }
}