Java 插件开发 动态加载 Jar
最编程
2024-03-09 11:50:32
...
背景
为了项目的扩展性,很多项目往往都会使用插件的方式为项目增加新功能,比如开发某种聊天机器人,增加扩展功能。这种方式非常灵活而且比较容易开发,本文就简单探讨一下Java如何动态加载Jar实现插件化开发。
规范或协议
在开始之前,首先需要定义一种规范,加载插件后如何调用插件内的方法,如何获取插件的名称版本号等信息。
如果有开发过安卓的Xposed插件应该知道,Xposed插件需要添加一个xposed_init文件,内容为入口类全名。
本文只是做个简单的演示,具体实现方式可以不同
此处我们定义plugin.properties作为插件的入口,加载jar后,读取mainClass的值作为入口类,版本号等信息可以自行添加,此处省略。
一般情况下,插件和项目都会依赖同一个库,插件去实现库中的接口或继承抽象类,项目加载插件调用方法,不过此处就不做演示。
编写插件
简单编写一个打印传入内容的插件
入口类
package cn.montaro.plugins;
public class Test {
public void print(String text) {
System.out.println("我是插件我被调用了");
System.out.println(text);
}
}
plugin.properties文件
mainClass=cn.montaro.plugins.Test
打包成jar
编写插件加载器
package cn.montaro.loader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.util.Properties;
public class PluginLoader {
private final static String PROPERTIES_NAME = "plugin.properties";
private final static String MAIN_CLASS = "mainClass";
/**
* 加载jar文件
*
* @param jarFilePath jar文件路径
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Class loadJar(String jarFilePath) throws IOException, ClassNotFoundException {
ClassLoader classLoader = getClassLoader(jarFilePath);
Properties properties = getProperties(classLoader, PROPERTIES_NAME);
String mainClass = properties.getProperty(MAIN_CLASS);
return loadClass(classLoader, mainClass);
}
/**
* 获得ClassLoader
*
* @param jarFilePath jar文件路径
* @return
* @throws MalformedURLException
*/
private static final ClassLoader getClassLoader(String jarFilePath) throws MalformedURLException {
File jarFile = new File(jarFilePath);
if (!jarFile.exists()) {
return null;
}
URL url = jarFile.toURI().toURL();
URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, null);
return classLoader;
}
/**
* 获得jar中的properties
*
* @param classLoader classLoader
* @param propertiesName 文件名称
* @return
* @throws IOException
*/
private static Properties getProperties(ClassLoader classLoader, String propertiesName) throws IOException {
InputStream propertiesStream = classLoader.getResourceAsStream(propertiesName);
Properties properties = new Properties();
properties.load(propertiesStream);
return properties;
}
/**
* 加载类
*
* @param classLoader classLoader
* @param className 全类名
* @return
* @throws ClassNotFoundException
*/
private static Class loadClass(ClassLoader classLoader, String className) throws ClassNotFoundException {
Class<?> clazz = classLoader.loadClass(className);
return clazz;
}
}
加载插件
将插件打包成jar
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
String jarFilePath = "D:\\Projects\\plugin-test\\target\\plugin-test-1.0-SNAPSHOT.jar";
Class mainClass = PluginLoader.loadJar(jarFilePath);
Object o = mainClass.newInstance();
Method print = mainClass.getDeclaredMethod("print", String.class);
print.invoke(o, "23333");
}
}
上一篇: JVM 系列(A):JAVA 类加载机制
下一篇: Java 类加载器说明 - Notes
推荐阅读
-
安卓插件学习路径(一)动态加载概述
-
Java 类加载器的作用 - 简介:类加载器是 Java™ 中一个非常重要的概念。类加载器负责将 Java 类的字节码加载到 Java 虚拟机中。本文首先详细介绍了 Java 类加载器的基本概念,包括代理模型、加载类的具体过程和线程上下文类加载器等。然后介绍了如何开发自己的类加载器,最后介绍了类加载器在 Web 容器和 OSGi™ 中的应用。 类加载器是 Java 语言的一项创新,也是 Java 语言广受欢迎的重要原因之一。它允许将 Java 类动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 开始出现,最初是为了满足 Java Applets 的需求而开发的,Java Applets 需要从远程位置下载 Java 类文件并在浏览器中执行。现在,类加载器已广泛应用于网络容器和 OSGi。一般来说,Java 应用程序的开发人员不需要直接与类加载器交互;Java 虚拟机的默认行为足以应对大多数情况。但是,如果遇到需要与类加载器交互的情况,而您又不太了解类加载器的机制,就很容易花费大量时间调试异常,如 ClassNotFoundException 和 NoClassDefFoundError。本文将详细介绍 Java 的类加载器,帮助读者深入理解 Java 语言中的这一重要概念。下面先介绍一些基本概念。 类加载器的基本概念 顾名思义,类加载器用于将 Java 类加载到 Java 虚拟机中。一般来说,Java 虚拟机以如下方式使用 Java 类:Java 源程序(.java 文件)经 Java 编译器编译后转换为 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码并将其转换为 java.lang 实例。每个实例都用来表示一个 Java 类。通过该实例的 newInstance 方法创建该类的对象。实际情况可能更加复杂,例如,Java 字节代码可能是由工具动态生成或通过网络下载的。 基本上,所有类加载器都是 java.lang.ClassLoader 类的实例。下面将详细介绍这个 Java 类。 java.lang.ClassLoader 类简介 java.lang.ClassLoader 类的基本职责是根据给定类的名称为其查找或生成相应的字节码,然后根据这些字节码定义一个 Java 类,即 java.lang.Class 类的实例。除此之外,ClassLoader 还负责加载 Java 应用程序所需的资源,如图像文件和配置文件。不过,本文只讨论它加载类的功能。为了履行加载类的职责,ClassLoader 提供了许多方法,其中比较重要的方法如表 1 所示。下文将详细介绍这些方法。 表 1.与加载类相关的 ClassLoader 方法
-
安卓插件的动态加载原理(二)
-
Java 插件开发 动态加载 Jar
-
Spring Boot 如何热加载 jar 以实现动态插件?
-
记录 - JAVA 动态加载外部 JAR 并调用方法和卸载以关闭打开的外部 JAR
-
Java] 在外部 Jars 中简单而优雅地加载类|插件化-设计在外部 Jars 中简单而优雅地加载类|插件化设计
-
类加载器动态替换 java 类_类加载器和类的热替换(Hotswap)
-
JAVA 如何通过类加载器加载类和 jar 包
-
java(类的常用方法 获取类对象的六种方法 动态加载和静态加载 类的加载过程)