java代碼實現利用 classloader 動態加載 jar包、文件夾到classpath中 – JAVA編程語言程序開發技術文章

all is well


在項目中實現瞭一個工具(獨立運行的Java工程,打成jar包後 通過 java -jar **.jar 執行的。),該工具通過配置能夠實現一些業務功能,
並且該工具提供瞭接口與抽象類,供其他人擴展它的功能。


這就涉及到一個問題:別人在擴展它的時候,需要引入一些jar或者配置文件,本來工具依賴的jar和配置文件都記錄在manifest文件中瞭,
不可能別人加瞭jar包和配置文件就要修改manifest文件的。
所以我為工具提供瞭另外一個入口,通過 該通過的配置文件 進行配置 路徑,由於考慮到擴展的人可能多人或者多組,所以配置文件如下定義:
以ext_classpath開頭的,諸如 ext_classpath_biz1等對應的路徑均被加入到classpath中。
以ext_resourcepath開頭的,諸如 ext_resourcepath_biz1等對應的路徑均被加入classpath中。


代碼實現如下:



package com.bz.utils;


import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;


/** *//**
 * 根據properties中配置的路徑把jar和配置文件加載到classpath中。
 * @author jnbzwm
 *
 */
public final class ExtClasspathLoader {
    /** *//** URLClassLoader的addURL方法 */
    private static Method addURL = initAddMethod();


    private static URLClassLoader classloader = (URLClassLoader) ClassLoader.getSystemClassLoader();


    /** *//**
     * 初始化addUrl 方法.
     * @return 可訪問addUrl方法的Method對象
     */
    private static Method initAddMethod() {
        try {
            Method add = URLClassLoader.class.getDeclaredMethod(“addURL”, new Class[] { URL.class });
            add.setAccessible(true);
            return add;
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /** *//**
     * 加載jar classpath。
     */
    public static void loadClasspath() {
        List<String> files = getJarFiles();
        for (String f : files) {
            loadClasspath(f);
        }


        List<String> resFiles = getResFiles();


        for (String r : resFiles) {
            loadResourceDir(r);
        }
    }


    private static void loadClasspath(String filepath) {
        File file = new File(filepath);
        loopFiles(file);
    }


    private static void loadResourceDir(String filepath) {
        File file = new File(filepath);
        loopDirs(file);
    }


    /** *//**   
     * 循環遍歷目錄,找出所有的資源路徑。
     * @param file 當前遍歷文件
     */
    private static void loopDirs(File file) {
        // 資源文件隻加載路徑
        if (file.isDirectory()) {
            addURL(file);
            File[] tmps = file.listFiles();
            for (File tmp : tmps) {
                loopDirs(tmp);
            }
        }
    }


    /** *//**   
     * 循環遍歷目錄,找出所有的jar包。
     * @param file 當前遍歷文件
     */
    private static void loopFiles(File file) {
        if (file.isDirectory()) {
            File[] tmps = file.listFiles();
            for (File tmp : tmps) {
                loopFiles(tmp);
            }
        }
        else {
            if (file.getAbsolutePath().endsWith(“.jar”) || file.getAbsolutePath().endsWith(“.zip”)) {
                addURL(file);
            }
        }
    }


    /** *//**
     * 通過filepath加載文件到classpath。
     * @param filePath 文件路徑
     * @return URL
     * @throws Exception 異常
     */
    private static void addURL(File file) {
        try {
            addURL.invoke(classloader, new Object[] { file.toURI().toURL() });
        }
        catch (Exception e) {
        }
    }


    /** *//**
     * 從配置文件中得到配置的需要加載到classpath裡的路徑集合。
     * @return
     */
    private static List<String> getJarFiles() {
        // TODO 從properties文件中讀取配置信息略
        return null;
    }


    /** *//**
     * 從配置文件中得到配置的需要加載classpath裡的資源路徑集合
     * @return
     */
    private static List<String> getResFiles() {
        //TODO 從properties文件中讀取配置信息略
        return null;
    }


    public static void main(String[] args) {
        ExtClasspathLoader.loadClasspath();
    }
}

發佈留言