猿问

Java 从目录中加载 jar 文件

我目前正在开发一个开源项目,人们可以添加自己的.jar来扩展所包含的功能。但是,我一直坚持如何在jar中加载类。

我有一个抽象类,它有一个抽象方法和一些getter,它提供了一些对象来处理应用程序。该插件需要子类我的插件类。jar应该添加到/plugins中,因此我希望在应用程序启动时加载/plugins文件夹中的所有*.jar文件。onEnable()BasePlugin

我现在遇到的问题是,在我发现的所有方法中,我需要在jar文件中声明类的类路径,我不知道。我也不知道 jar 文件的名称。因此,我需要扫描 /plugins 文件夹中的任何 *.jar 文件,并在实现和调用该方法的 jar 中加载相应的类。BasePluginonEnable()


胡子哥哥
浏览 203回答 4
4回答

Smart猫小萌

基本思想也是...读取特定目录中的所有文件将每个结果的引用转换为FileURL使用与结果一起设定种子的 ,加载每个结果URLClassLoaderURL用于查找具有特定名称的所有匹配资源URLClassLoader#findResources迭代匹配的资源并加载每个资源,这至少应该给出“入口点”类名装入由“入口点”属性指定的类例如。。。public List<PluginClass> loadPlugins() throws MalformedURLException, IOException, ClassNotFoundException {&nbsp; &nbsp; File plugins[] = new File("./Plugins").listFiles(new FileFilter() {&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public boolean accept(File file) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return file.getName().endsWith(".jar");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; });&nbsp; &nbsp; List<URL> plugInURLs = new ArrayList<>(plugins.length);&nbsp; &nbsp; for (File plugin : plugins) {&nbsp; &nbsp; &nbsp; &nbsp; plugInURLs.add(plugin.toURI().toURL());&nbsp; &nbsp; }&nbsp; &nbsp; URLClassLoader loader = new URLClassLoader(plugInURLs.toArray(new URL[0]));&nbsp; &nbsp; Enumeration<URL> resources = loader.findResources("/META-INFO/Plugin.properties");&nbsp; &nbsp; List<PluginClass> classes = new ArrayList<>(plugInURLs.size());&nbsp; &nbsp; while (resources.hasMoreElements()) {&nbsp; &nbsp; &nbsp; &nbsp; URL resource = resources.nextElement();&nbsp; &nbsp; &nbsp; &nbsp; Properties properties = new Properties();&nbsp; &nbsp; &nbsp; &nbsp; try (InputStream is = resource.openStream()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; properties.load(is);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String className = properties.getProperty("enrty-point");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PluginClass pluginClass = loader.loadClass(className);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; classes.add(pluginClass);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return classes}nb:我没有运行这个,但这是“基本”

天涯尽头无女友

SpigotMC也使用JAR文件作为插件,jar内部是一个文件,用于存储有关插件的额外信息,包括类路径。您不需要使用 YAML 文件,而是可以使用 JSON 甚至纯文本文件之类的文件。plugin.yamlYAML 文件位于 jar 中,可以使用此处介绍的一些方法来访问该文件。然后,您可以获取类路径属性,然后使用此处介绍的方法加载 jar。可以存储有关插件的额外信息,例如名称,版本和依赖项。

慕婉清6462132

Java已经有一个这样的类:服务加载器。服务加载器类是随 Java 6 引入的,但“SPI jar”概念实际上与 Java 1.3 一样古老。这个想法是每个jar都包含一个简短的文本文件,该文件描述了其特定服务提供者接口的实现。例如,如果一个.jar文件包含两个名为 FooPlugin 和 BarPlugin 的 BasePlugin 子类,则该.jar文件还将包含以下条目:META-INF/services/com.example.BasePlugin该 jar 条目将是一个文本文件,包含以下行:com.myplugins.FooPlugincom.myplugins.BarPlugin您的项目将通过创建一个从目录中读取的类加载器来扫描插件:pluginsCollection<URL> urlList = new ArrayList<>();Path pluginsDir = Paths.get(&nbsp; &nbsp; System.getProperty("user.home"), "plugins");try (DirectoryStream<Path> jars =&nbsp; &nbsp; Files.newDirectoryStream(pluginsDir, "*.jar")) {&nbsp; &nbsp; for (Path jar : jars) {&nbsp; &nbsp; &nbsp; &nbsp; urlList.add(jar.toUri().toURL());&nbsp; &nbsp; }}URL[] urls = urlList.toArray(new URL[0]);ClassLoader pluginClassLoader = new URLClassLoader(urls,&nbsp; &nbsp; BasePlugin.class.getClassLoader());ServiceLoader<BasePlugin> plugins =&nbsp; &nbsp; ServiceLoader.load(BasePlugin.class, pluginClassLoader);for (BasePlugin plugin : plugins) {&nbsp; &nbsp; plugin.onEnable();&nbsp; &nbsp; // etc.}使用 ServiceLoader 的另一个优点是,您的代码将能够与模块一起使用,这是 Java 9 引入的更完整的代码封装形式,可提供更高的安全性。

哆啦的时光机

这里有一个例子,它可能会有所帮助。另外,你应该看看OSGi。
随时随地看视频慕课网APP

相关分类

Java
我要回答