我正在尝试写我自己的小插件加载程序:
package some.package.plugins
import org.clapper.classutil.{ClassFinder, ClassInfo}
import wvlet.log.LogSupport
import java.io.File
import java.net.{URL, URLClassLoader}
object PluginManager extends LogSupport {
val PLUGIN_DIRECTOR = "./plugins/"
val PLUGIN_INTERFACE = "package.Plugin"
val jars: List[File] = new File(PLUGIN_DIRECTOR).listFiles.filter(_.getPath.endsWith(".jar")).toList
private val pluginMap : Map[String,(ClassInfo,File)] = {
jars.flatMap {
jar =>
val finder = ClassFinder(List(jar))
println(finder.getClasses().map(_.interfaces).toList)
finder.getClasses().filter(_.interfaces.contains(PLUGIN_INTERFACE)).map {
info =>
info.name.split("\\.").last -> (info, jar)
}
}.toMap
}
def getPlugins : Set[String] = pluginMap.keySet
def loadPlugins(name : String) : AnalysisPlugin = {
val classInfo : (ClassInfo,File) = pluginMap.getOrElse(name,throw new IllegalArgumentException(s"the plugin $name does not exist"))
val urls : List[URL] = List(classInfo._2.toURI.toURL)
val childClassLoader = URLClassLoader.newInstance(urls.toArray, ClassLoader.getSystemClassLoader)
info(s"loading plugin ${classInfo._1.name}")
val c: Class[_] = childClassLoader.loadClass(classInfo._1.name)
assert(c.getConstructors.length == 1)
c.getConstructors.head.newInstance().asInstanceOf[AnalysisPlugin]
}
}
我使用ClassFinder
和ClassInfo
来标识.jar
中实现PLUGIN_INTERFACE
的所有类。输出确认我确实找到了实现PLUGIN_INTERFACE
的类。然后,我使用URLClassLoader
(与childClassLoader.loadClass
一起提供)来加载相应的类,但我得到了NoClassDefFound
异常。
这里的问题似乎是接口类,即,应该使不同插件对插件管理器透明的接口。package.Plugin
是不能加载的类。
如何使用URLClassLoader
加载包含在.jar
中的类。
1条答案
按热度按时间9gm1akwq1#
我不理解底层逻辑,但您需要为
URLClassLoader
提供一个不同的父类加载器,经过一些模糊处理后,我成功地使用包含main函数的对象的类加载器运行了代码: