相信在实际工作中,大家可能会遇到这种需求,这个jar是外部的,并没有添加到项目依赖中,只能通过类加载器加载并调用相关方法。
这种jar加载,其实也简单,我们通过普通的URLClassLoader就可以加载。代码如下所示:
public static URLClassLoader getClassLoader(String url) {
URLClassLoader classLoader = new URLClassLoader(new URL[]{}, ClassLoader.getSystemClassLoader());
try {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
if (!method.isAccessible()) {
method.setAccessible(true);
}
method.invoke(classLoader, new URL("file:" + url));
return classLoader;
} catch (NoSuchMethodException | MalformedURLException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
这里,只是把jar加载到了虚拟机中,要调用,我们需要根据类名与类加载器来 获取类对象。
public static List<Class<?>> getClassListByInterface(String url, ClassLoader classLoader, Class<?> clazz) {
List<Class<?>> classList = new ArrayList<>();
if (!clazz.isInterface()) {
return classList;
}
List<String> classNames = new ArrayList<>();
try (JarFile jarFile = new JarFile(url)) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
String entryName = jarEntry.getName();
if (entryName != null && entryName.endsWith(".class")) {
entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
classNames.add(entryName);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
if (classNames.size() > 0) {
for (String className : classNames) {
try {
Class<?> theClass = classLoader.loadClass(className);
if (clazz.isAssignableFrom(theClass) && !theClass.equals(clazz)) {
classList.add(theClass);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
return classList;
}
还需要做一些准备:
1,定义一个接口,外部去实现:
import java.util.Map;
public interface IService {
String name();
Object process(Map<String, Object> params);
}
2、三方实现:
import com.example.service.IService;
im