silentbalanceyh/vertx-zero

View on GitHub
vertx-gaia/vertx-ams/src/main/java/io/horizon/util/HSPI.java

Summary

Maintainability
A
35 mins
Test Coverage
package io.horizon.util;

import io.horizon.exception.internal.SPINullException;

import java.util.*;

/**
 * @author lang : 2023/4/27
 */
final class HSPI {
    private HSPI() {
    }

    static <T> Collection<T> services(final Class<T> clazz) {
        return services(clazz, null);
    }

    static <T> Collection<T> services(final Class<T> clazz, final ClassLoader classLoader) {
        final List<T> list = new ArrayList<>();
        ServiceLoader<T> factories;
        if (classLoader != null) {
            factories = ServiceLoader.load(clazz, classLoader);
        } else {
            // 等价代码:ServiceLoader.load(clazz, TCCL);
            factories = ServiceLoader.load(clazz);
        }
        if (factories.iterator().hasNext()) {
            factories.iterator().forEachRemaining(list::add);
            return list;
        } else {
            // 默认使用 TCCL,但在 OSGi 环境中可能不够,因此尝试使用加载此类的类加载器,所以为了兼容 osgi 环境,需要使用
            // ServiceLoader.load(clazz, Spi.class.getClassLoader()) 加载
            factories = ServiceLoader.load(clazz, HSPI.class.getClassLoader());
            if (factories.iterator().hasNext()) {
                factories.iterator().forEachRemaining(list::add);
                return list;
            } else {
                return Collections.emptyList();
            }
        }
    }

    static <T> T service(final Class<T> interfaceCls, final Class<?> caller, final boolean strict) {
        final ClassLoader loader = Optional.ofNullable(caller).map(Class::getClassLoader).orElse(null);
        return service(interfaceCls, loader, strict);
    }

    static <T> T service(final Class<T> interfaceCls, final ClassLoader loader, final boolean strict) {
        final Collection<T> collection = services(interfaceCls, loader);
        final T service;
        if (!collection.isEmpty()) {
            service = collection.iterator().next();
        } else {
            service = null;
        }
        if (Objects.isNull(service) && strict) {
            throw new SPINullException(HSPI.class);
        }
        return service;
    }
}