从shardingsphere源码提取出来的一种spi实现机制的代码,挺有意思的,分享一下

源码

https://gitee.com/you-jianming/code/tree/master/src/main/java/spi

/**
 * 描述:仿造shardingsphere的一个spi的实现
 *
 * @author Madison You
 * @created 14:17
 */
public class ShardingSphereSpiDemo {

    public static void main(String[] args) {

        /*new出一个主键策略的实例,自动将spi进行注册,通过uuid类型,查找出对应的  ShardingKeyGenerator  实现类*/
        ShardingKeyGenerator shardingKeyGenerator = new ShardingKeyGeneratorServiceLoader().newService("UUID", new Properties());
        System.out.println(shardingKeyGenerator);
    }

}
/**
 * 描述:自定义一个spi加载类
 *
 * @author Madison You
 * @created 14:40
 */
public final class ShardingKeyGeneratorServiceLoader extends TypeBasedSPIServiceLoader<ShardingKeyGenerator> {

    static {
        /*将自定义的接口注册进一个全局的spi加载集合*/
        NewInstanceServiceLoader.register(ShardingKeyGenerator.class);
    }

    public ShardingKeyGeneratorServiceLoader() {
        super(ShardingKeyGenerator.class);
    }
}
/**
 * 描述:spi注册类
 *
 * @author Madison You
 * @created 14:27
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NewInstanceServiceLoader {

    private static final Map<Class, Collection<Class<?>>> SERVICE_MAP = new HashMap<>();

    public static <T> void register(final Class<T> service) {
        for (T each : ServiceLoader.load(service)) {
            registerServiceClass(service, each);
        }
    }

    /**
     * 描述:注册方法,将spi注册进 SERVICE_MAP,以便于通过type进行加载
     *
     * @author Madison You
     * @created 2022/4/23 15:05:00
     * @param
     * @return
     */
    private static <T> void registerServiceClass(final Class<T> service, final T instance) {
        Collection<Class<?>> serviceClasses = SERVICE_MAP.get(service);
        if (null == serviceClasses) {
            serviceClasses = new LinkedHashSet<>();
        }
        serviceClasses.add(instance.getClass());
        SERVICE_MAP.put(service, serviceClasses);
    }

    @SneakyThrows
    public static <T> Collection<T> newServiceInstances(final Class<T> service) {
        Collection<T> result = new LinkedList<>();
        if (null == SERVICE_MAP.get(service)) {
            return result;
        }
        for (Class<?> each : SERVICE_MAP.get(service)) {
            result.add((T) each.newInstance());
        }
        return result;
    }

}
@RequiredArgsConstructor
public abstract class TypeBasedSPIServiceLoader<T extends TypeBasedSPI>{

    private final Class<T> classType;

    public final T newService(final String type, final Properties props) {
        Collection<T> typeBasedServices = loadTypeBasedServices(type);
        if (typeBasedServices.isEmpty()) {
            throw new RuntimeException(String.format("Invalid `%s` SPI type `%s`.", classType.getName(), type));
        }
        T result = typeBasedServices.iterator().next();
        result.setProperties(props);
        return result;
    }

    public final T newService() {
        T result = loadFirstTypeBasedService();
        result.setProperties(new Properties());
        return result;
    }

    private Collection<T> loadTypeBasedServices(String type) {
        return Collections2.filter(NewInstanceServiceLoader.newServiceInstances(classType), input -> type.equalsIgnoreCase(input.getType()));
    }

    private T loadFirstTypeBasedService() {
        Collection<T> instances = NewInstanceServiceLoader.newServiceInstances(classType);
        if (instances.isEmpty()) {
            throw new RuntimeException(String.format("Invalid `%s` SPI, no implementation class load from SPI.", classType.getName()));
        }
        return instances.iterator().next();
    }
}
/**
 * 描述:定义基础的spi类型接口
 *
 * @author Madison You
 * @created 14:18
 */
public interface TypeBasedSPI {

    /**
     * 描述:获取类型
     *
     * @author Madison You
     * @created 2022/4/23 14:19:00
     * @param
     * @return
     */
    String getType();

    /**
     * 描述:获取配置
     *
     * @author Madison You
     * @created 2022/4/23 14:20:00
     * @param
     * @return
     */
    Properties getProperties();

    /**
     * 描述:设置配置属性
     *
     * @author Madison You
     * @created 2022/4/23 14:20:00
     * @param
     * @return
     */
    void setProperties(Properties properties);
}
/**
 * 描述:定义一个主键生成的接口
 *
 * @author Madison You
 * @created 14:35
 */
public interface ShardingKeyGenerator extends TypeBasedSPI {

    Comparable<?> generateKey();

}
/**
 * 描述:uuid主键生成接口
 *
 * @author Madison You
 * @created 14:36
 */
@Getter
@Setter
public final class UUIDShardingKeyGenerator implements ShardingKeyGenerator {

    private Properties properties = new Properties();

    @Override
    public String getType() {
        return "UUID";
    }

    @Override
    public synchronized Comparable<?> generateKey() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
}
      <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.0.1-jre</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

你可能感兴趣的:(源码,java,java)