博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【java】 java SPI
阅读量:6608 次
发布时间:2019-06-24

本文共 3301 字,大约阅读时间需要 11 分钟。

 

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
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)的全类名的文件内容,加载类。

 

转载地址:http://xciso.baihongyu.com/

你可能感兴趣的文章
js删除提醒
查看>>
Codeforces Round #257 (Div. 2) C. Jzzhu and Chocolate
查看>>
UVA 10177 Sqr/Rects/Cubes/Boxes?
查看>>
数学图形之锥体
查看>>
使用CoreData [2]
查看>>
OGRFeature的DestroyFeature方法
查看>>
(转)Inno Setup入门(三)——指定压缩方式
查看>>
jQuery与GridView控件结合示例
查看>>
SqlCommandBuilder的作用
查看>>
【JavaScript】一些注意点
查看>>
用pyinstaller把python代码打包成exe可执行文件
查看>>
Jexus web server V5.6.1正式公布
查看>>
优先级队列-堆实现
查看>>
Unity3D ogg下载并播放
查看>>
MemCached配置与缓存知识概述
查看>>
ASP.net--全局程序文件:Global.asax
查看>>
抽象类做函数参数问题
查看>>
深入探讨 java.lang.ref 包--转
查看>>
荷兰国旗问题
查看>>
微信怎样加入精准粉丝
查看>>