• 【java】 java SPI


    SPI(Service provider interface)是旨在由第三方实现或扩展的API。它可以用于启用框架扩展和可替换组件。

    服务是一组众所周知的接口或(通常是抽象的)类。服务提供者是服务的特定实现。提供程序中的类通常实现接口并对服务本身中定义的类进行子类化。服务提供程序可以以扩展的形式安装在Java平台的实现中,即,jar文件放置在任何通常的扩展目录中。提供者也可以通过将它们添加到应用程序的类路径或通过一些其他平台特定的手段。

    在java中通过java.util.ServiceLoader 来实现。

    先上代码:

    Provider 可以为接口或者抽象类

    package com.xwolf.spi.service;
    /**
     * Animal Provider
     * @author xwolf
     *
     */
    public interface Animal {
        
        void eat();
        
        void drink();
    
    }

    具体实现:

    package com.xwolf.spi.service.impl;
    
    import com.xwolf.spi.service.Animal;
    
    public class Dog implements Animal {
    
        @Override
        public void eat() {
            System.out.println("Dog eat....");
        }
    
        @Override
        public void drink() {
            System.out.println("Dog drink....");
        }
    
    }
    package com.xwolf.spi.service.impl;
    
    
    import com.xwolf.spi.service.Animal;
    
    public class Cat implements Animal {
    
        @Override
        public void eat() {
            System.out.println("Cat eat....");
        }
    
        @Override
        public void drink() {
            System.out.println("Cat drink...");
        }
    
    }

    将接口和具体实现放在文件META-INF/services中,文件名为全类名的Provider,内容为具体实现类的全类名。

    测试方法:

    package com.xwolf.spi.service;
    
    import java.util.ServiceLoader;
    
    public class ServiceLoaderTest {
        
        public static void main(String[] args) {
            //接口测试
            ServiceLoader<Animal> loader=ServiceLoader.load(Animal.class);
            for(Animal animal:loader){
                animal.eat();
            }
    
        }
    
    }

    项目目录结构:

     查看ServiceLoader部分源代码:

    private boolean hasNextService() {
                if (nextName != null) {
                    return true;
                }
                if (configs == null) {
                    try {
                        String fullName = PREFIX + service.getName();
                        if (loader == null)
                            configs = ClassLoader.getSystemResources(fullName);
                        else
                            configs = loader.getResources(fullName);
                    } catch (IOException x) {
                        fail(service, "Error locating configuration files", x);
                    }
                }
                while ((pending == null) || !pending.hasNext()) {
                    if (!configs.hasMoreElements()) {
                        return false;
                    }
                    pending = parse(service, configs.nextElement());
                }
                nextName = pending.next();
                return true;
            }
    
            private S nextService() {
                if (!hasNextService())
                    throw new NoSuchElementException();
                String cn = nextName;
                nextName = null;
                Class<?> c = null;
                try {
                    c = Class.forName(cn, false, loader);
                } catch (ClassNotFoundException x) {
                    fail(service,
                         "Provider " + cn + " not found");
                }
                if (!service.isAssignableFrom(c)) {
                    fail(service,
                         "Provider " + cn  + " not a subtype");
                }
                try {
                    S p = service.cast(c.newInstance());
                    providers.put(cn, p);
                    return p;
                } catch (Throwable x) {
                    fail(service,
                         "Provider " + cn + " could not be instantiated",
                         x);
                }
                throw new Error();          // This cannot happen
            }

    比较核心的代码就上边了,总之就是遍历的时候读取META-INF/services下所有为CLASS(本例子中的Animal)的全类名的文件内容,加载类。

     

  • 相关阅读:
    python_控制台输出带颜色的文字方法
    模拟数据库作业
    js笔记
    CSS 笔记
    html 笔记
    必备技能-Git 使用规范流程
    python 闭包
    30个python编程技巧!
    python 面向对象
    python 线程
  • 原文地址:https://www.cnblogs.com/lonelywolfmoutain/p/6439308.html
Copyright © 2020-2023  润新知