java spi demo实现
2022-11-10 本文已影响0人
arkliu
实现端工程
image.pngLog接口
package com.test.spi;
public interface Log {
public void printLog(String str);
}
AdbLog 实现类
package com.test.spi.impl;
import com.test.spi.Log;
public class AdbLog implements Log {
@Override
public void printLog(String str) {
System.out.println("from AdbLog:"+str);
}
}
Log4j实现类
package com.test.spi.impl;
import com.test.spi.Log;
public class Log4j implements Log {
@Override
public void printLog(String str) {
System.out.println("from log4j:"+str);
}
}
实现端
image.pngLog接口声明
package com.test.spi;
public interface Log {
public void printLog(String str);
}
-
新建“META-INF/services/” 目录,目录名字要严格一致,因为ServiceClassLoader里是定义了这样的路径
image.png - 在“META-INF/services/” 目录下新建一个文件,文件名称为,声明接口的全类名。 本例为:"com.test.spi.Log"
-
第二步新建的"com.test.spi.Log"文件的内容为,Log接口实现类的全类名,如下:
image.png - 使用ServiceLoader加载实现类。
package com.test.spi;
import java.util.Iterator;
import java.util.ServiceLoader;
import com.test.spi.impl.Log4j;
public class TestLog {
public static void main(String[] args) {
// 1. 获取原本的ClassLoader
ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
try {
ServiceLoader<Log> serviceLogs = ServiceLoader.load(Log.class);
// 2. 使用自定义的ClassLoader
// ServiceLoader<Log> serviceLogs = ServiceLoader.load(Log.class, 这里可以写自定义的ClassLoader);
Iterator<Log>iterLogs = serviceLogs.iterator();
while (iterLogs.hasNext()) {
Log log = iterLogs.next();
System.out.println(log.getClass());
if (log instanceof Log4j) {
log.printLog("hello");
} else {
log.printLog("spi");
}
}
} finally {
//3.恢复原本的ClassLoader
Thread.currentThread().setContextClassLoader(originalLoader);
}
}
}
执行结果:
image.png