java系统的插件开发,类似 系统中定义一个 接口,给插件的开发者,然后开发者按照实现该接口后,打包成jar(zip) 上传到系统中,并告知系统实现类的名字,然后系统就能调用该插件了。
该实现方法用到了 java动态加载 类的技术,主要是ClassLoader。
下面 我们模拟 一个场景
一个系统 提供一个打印功能,其接口是IPrinter。该系统 已经实现了 老式打印机OldPrinterImpl。
现在第三方 拿到 IPrinter 接口后 开发出了 ColorPrinterImpl 彩色打印的功能。并打成了插件zip(jar)包,上传到了 系统,并告知系统打印使用ColorPrinterImpl 。
代码如下:
本系统中的代码
IPrinter.java
package com.iccboy.study.plugin.api;
/**
* 打印接口
*
* @author iccboy
*/
public interface IPrinter {
/**
* 打印
* @param msg 内容
* @return 打印值
*/
String print(String msg);
}
OldPrinterImpl.java
package com.iccboy.study.plugin.myimpl;
import com.iccboy.study.plugin.api.IPrinter;
/**
* 照片打印
* @author iccboy
*
*/
public class OldPrinterImpl implements IPrinter {
@Override
public String print(String msg) {
return "这是老式打印机打印出的内容:" + msg;
}
}
Client.java
package com.iccboy.study.plugin;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import com.iccboy.study.plugin.api.IPrinter;
import com.iccboy.study.plugin.myimpl.OldPrinterImpl;
/**
* 场景类
* @author iccboy
*
*/
public class Client {
public static void main(String[] args) {
IPrinter print = new OldPrinterImpl();
String msg = print.print("枯藤老树昏鸦,古道西风瘦马");
System.out.println(msg);
print = getPrinter("com.iccboy.study.plugin.otherimpl.ColorPrinterImpl");
System.out.println(print.print("沉舟侧畔千帆过,病树前头万木春"));
}
/**
* 获得插件中的实现
* @param className
* @return
*/
public static IPrinter getPrinter(String className) {
String class_path = className;//Jar中的所需要加载的类的类名
String jar_path = "D:\\case\\java\\plugin\\colorpinter.zip";//jar所在的文件的URL
try {
ClassLoader cl = new URLClassLoader(new URL[]{new File(jar_path).toURI().toURL()});//从Jar文件得到一个Class加载器
Class<?> c = cl.loadClass(class_path);//从加载器中加载Class
IPrinter sif = (IPrinter) c.newInstance();//从Class中实例出一个对象
return sif;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
接下来,我们把IPrinter.java 接口类 分发给插件开发者,插件开发者 将 接口导入自己的项目中,然后实现该接口。然后导出为jar或者zip,把包给系统,使用方法如上面的Client.java类。
插件项目printer-plugin
ColorPrinterImpl.java
package com.iccboy.study.plugin.otherimpl;
import com.iccboy.study.plugin.api.IPrinter;
/**
*
* 彩色打印机 插件实现
* @author iccboy
*
*/
public class ColorPrinterImpl implements IPrinter {
@Override
public String print(String msg) {
return "这是彩色打印机打印出的内容:" + msg + "\r\n" +
new OtherClass().getSoming();
}
}
OtherClass.java
package com.iccboy.study.plugin.otherimpl;
/**
* 插件中的其它类
* @author iccboy
*
*/
public class OtherClass {
public String getSoming() {
return "这是插件其它类中的数据";
}
}
然后打包
这是老式打印机打印出的内容:枯藤老树昏鸦,古道西风瘦马
这是彩色打印机打印出的内容:沉舟侧畔千帆过,病树前头万木春
这是插件其它类中的数据
这是彩色打印机打印出的内容:沉舟侧畔千帆过,病树前头万木春
这是插件其它类中的数据
最终运行结果是:
---------------------------------
这是老式打印机打印出的内容:枯藤老树昏鸦,古道西风瘦马
这是彩色打印机打印出的内容:沉舟侧畔千帆过,病树前头万木春
这是插件其它类中的数据
这是彩色打印机打印出的内容:沉舟侧畔千帆过,病树前头万木春
这是插件其它类中的数据
---------------------------------