1. 程式人生 > 實用技巧 >熱載入解除安裝jar包

熱載入解除安裝jar包

熱載入解除安裝jar包

2020-12-29

1 類層次

2 原始碼

原始碼

hot-load-unload-jar專案

PluginClassLoader.java內容如下:

package com.test;

import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/**
 * 外掛類載入器,在外掛目錄中搜索jar包,併為發現的資源(jar)構造一個類載入器,將對應的jar新增到classpath中
 * 
@author strawxdl */ public class PluginClassLoader extends URLClassLoader { private List<JarURLConnection> cachedJarFiles = new ArrayList<JarURLConnection>(); public PluginClassLoader() { super(new URL[] {}, findParentClassLoader()); } /** * 將指定的檔案url新增到類載入器的classpath中去,並快取jar connection,方便以後解除安裝jar *
@param 一個可想類載入器的classpath中新增的檔案url */ public void addURLFile(URL file) { try { // 開啟並快取檔案url連線 URLConnection uc = file.openConnection(); if (uc instanceof JarURLConnection) { uc.setUseCaches(true); ((JarURLConnection) uc).getManifest(); cachedJarFiles.add((JarURLConnection)uc); } }
catch (Exception e) { System.err.println("Failed to cache plugin JAR file: " + file.toExternalForm()); } addURL(file); } /** * 解除安裝jar包 */ public void unloadJarFiles() { for (JarURLConnection url : cachedJarFiles) { try { System.err.println("Unloading plugin JAR file " + url.getJarFile().getName()); url.getJarFile().close(); url=null; } catch (Exception e) { System.err.println("Failed to unload JAR file\n"+e); } } } /** * 定位基於當前上下文的父類載入器 * @return 返回可用的父類載入器. */ private static ClassLoader findParentClassLoader() { ClassLoader parent = PluginManager.class.getClassLoader(); if (parent == null) { parent = PluginClassLoader.class.getClassLoader(); } if (parent == null) { parent = ClassLoader.getSystemClassLoader(); } return parent; } }
View Code

PluginManager.java內容如下:

package com.test;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * jar包 熱載入/解除安裝 的初步實現
 * https://www.cnblogs.com/xiaodl/p/plugin_hot_load.html
 */
public class PluginManager {
    static{
        System.out.println(PluginManager.class.getName());
    }
    private Map<String ,PluginClassLoader> pluginMap = new HashMap<String,PluginClassLoader>();
    private static String packagename = "com.test.Plugin1";
    public PluginManager(){

    }

    public void doSome(String pluginName){

        try{
            Class<?> forName = Class.forName(packagename, true, getLoader(pluginName));//this.pluginMap.get(pluginName).loadClass(packagename);
            Plugin ins = (Plugin)forName.newInstance();
            ins.doSome();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    private void addLoader(String pluginName,PluginClassLoader loader){
        this.pluginMap.put(pluginName, loader);
    }
    private PluginClassLoader getLoader(String pluginName){
        return this.pluginMap.get(pluginName);
    }
    public void loadPlugin(String pluginName){
        this.pluginMap.remove(pluginName);
        PluginClassLoader loader = new PluginClassLoader();
        String pluginurl = "jar:file:/D:/code/plugindemo/target/"+pluginName+".jar!/";
        URL url = null;
        try {
            url = new URL(pluginurl);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        loader.addURLFile(url);
        addLoader(pluginName, loader);
        System.out.println("load " + pluginName + "  success");
    }
    public void unloadPlugin(String pluginName){
        this.pluginMap.get(pluginName).unloadJarFiles();
        this.pluginMap.remove(pluginName);
    }
}
View Code

TestMain.java內容如下:

package com.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TestMain {

    public static void main(String[] args) throws Exception {
        PluginManager manager = new PluginManager();;

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String cmd = br.readLine();

        while(!cmd.equals("bye")){
            if(cmd.startsWith("do")){
                String pluginName = cmd.split(" ")[1];
                manager.doSome(pluginName);
            }
            if(cmd.startsWith("load")){
                String pluginName = cmd.split(" ")[1];
                manager.loadPlugin(pluginName);
            }
            if(cmd.startsWith("unload")){
                String pluginName = cmd.split(" ")[1];
                manager.unloadPlugin(pluginName);
            }
            cmd = br.readLine();
        }
    }
}
View Code

plugin-contract專案

Plugin.java

package com.test;

public interface Plugin {
    public void doSome();
}

plugin-demo專案

Plugin1.java內容如下:

package com.test;

public class Plugin1 implements Plugin{
    public void doSome(){
        System.out.println("Plugin1 doSome ... is I? YES.");
    }
}

備註:

打包成 plugin-demo-1.0-SNAPSHOT.jar

Plugin1.java 內容1:System.out.println("Plugin1 doSome ... is I? YES."); 內容2:System.out.println("Plugin1 doSome ... is I? No.");

3 執行演示

參考:

[1] jar包 熱載入/解除安裝 的初步實現