我正在创建一个框架,该框架公开了供开发人员使用的API:
public interface MyAPI { public void doSomeStuff(); public int getWidgets(boolean hasRun); }
开发人员应该做的就是针对这些API方法编写项目代码。我还希望它们能够在运行时类路径上放置不同的“驱动程序” /“ API绑定”(与JDBC或SLF4J的工作方式相同),并使API方法调用(doSomeStuff()等)在不同的第三方资源(文件)上运行,服务器等)。因此,相同的代码和API调用将映射到操作上的不同资源,这取决于驱动器/绑定运行时类路径看(即myapi- ftp,myapi-ssh,myapi-teleportation)。
doSomeStuff()
myapi- ftp
myapi-ssh
myapi-teleportation
我怎样写(和封装)的SPI允许这样的运行时绑定, 并 再映射MyAPI调用正确的(混凝土)执行?换句话说,如果myapi- ftp允许您getWidgets(boolean)从FTP服务器访问,该如何处理(以同时使用API和SPI)?
MyAPI
getWidgets(boolean)
具体的,有效的Java代码示例的加分项!提前致谢!
看一看java.util.ServiceLoader类。
通常,这个想法是这样的:
API罐
绑定/驱动程序罐
javadocs中有一个很好的例子:
http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
package com.foo; public interface FooInterface { ... } public class FooInterfaceFactory { public static FooInterface newFooInstance() { ServiceLoader<FooInterface> loader = ServiceLoader.load(FooInterface.class); Iterator<FooInterface> it = loader.iterator(); // pick one of the provided implementations and return it. }
package com.myfoo; public class MyFooImpl implements FooInterface { ... } META-INF/com.foo.FooInterface com.myfoo.MyFooImpl
编辑
public interface FooSpi { void accepts(String url); FooInterface getFooInstance(); } public class FooInterfaceFactory { public static FooInterface getFooInterfaceInstance(String url) { ServiceLoader<FooSpi> loader = ServiceLoader.load(FooSpi.class); Iterator<FooSpi> it = loader.iterator(); while (it.hasNext()) { FooSpi fooSpi = it.next(); if (fooSpi .accepts(url)) { return fooSpi.getFooInstance(); } } return null; } }
当然,将文件名更改为com.foo.FooSpi并提供FooSpi的实现。这样您就可以将公共API与Spi接口隔离开来。
如果要隐藏accepts方法,则始终可以有第二个接口,它是您的公共API,并且