动态加载类

 

大家应该都听过热部署。热部署可以使应用程序在不全部重新编译,不停止服务的情况下,增加新功能,修复bug。使用Java如何实现这样的功能呢?动态加载类功不可没。

 

先给出一段简单的代码。该程序会修改classpath来增加运行时的jar包,并使用URLClassLoader来加载指定的类,以达到热部署的效果。

 

p.s. 简化处理的代码片段,不能处理UNC URL,获取home path的时候不考虑Mac平台的特殊性。诸多缺陷仅供演示。

 

package com.joshua.test;  
  
import java.io.File;  
import java.io.FilenameFilter;  
import java.io.IOException;  
import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.net.URLClassLoader;  
import java.security.AccessController;  
import java.util.LinkedList;  
import java.util.List;  
import java.util.StringTokenizer;  
  
public class ClassLoaderTest {  
  
    private static final String CLASSPATH_SEPARATOR = System.getProperty("path.separator");  
      
    private static ClassLoader classLoader;  
      
    static {  
        String classPath = System.getProperty("java.class.path");  
        String homePath = getHomePath(classPath);  
        File[] jars = new File(homePath + "/lib").listFiles(new FilenameFilter() {  
            @Override  
            public boolean accept(File dir, String name) {  
                return dir.canRead() & name.endsWith(".jar");  
            }  
        });  
          
        // Add jars in lib dir into classpath.  
        final List<URL> jarPaths = new LinkedList<URL>();  
        StringBuilder classPathSB = new StringBuilder(classPath);  
        for (File jar : jars) {  
            try {  
                jarPaths.add(jar.toURI().toURL());  
                classPathSB.append(CLASSPATH_SEPARATOR);  
                classPathSB.append(jar.getPath());  
            } catch (MalformedURLException e) {  
                e.printStackTrace();  
            }  
        }  
          
        // Modify the classpath  
        System.setProperty("java.class.path", classPathSB.toString());  
          
        classLoader = AccessController.doPrivileged(  
            new java.security.PrivilegedAction<URLClassLoader>() {  
                @Override  
                public URLClassLoader run() {  
                    return new URLClassLoader(jarPaths.toArray(new URL[jarPaths.size()]));  
                }  
            }  
        );  
          
        Class clazz = null;  
        try {  
            clazz = classLoader.loadClass("$全类名");  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        }  
        if (clazz == null) System.exit(-1);  
          
        Object loadedInstance = null;  
        try {  
            loadedInstance = clazz.newInstance();  
        } catch (InstantiationException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        }  
        if (loadedInstance == null) System.exit(-1);  
    }  
  
    public static String getHomePath(String classPath) {  
        StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);  
        String binPath = null;  
        if (st.countTokens() > 0) {  
            binPath = st.nextToken();  
        }  
        try {  
            return new File(binPath).getCanonicalFile().getParent();  
        } catch (IOException e) {  
            e.printStackTrace();  
            return "";  
        }  
    }  
     
}  

 

 

你可能感兴趣的:(java,类加载,动态加载类)