Java_动态重新加载Class总结

在此记载Java动态重新加载Class的点点滴滴,实现之前也在网上看了很多文章,但发现不是很清晰,后来发现总结,看源码实现还是最靠谱。

直接上代码:

package com.lkb.autoCode.util;

import com.lkb.autoCode.constant.AutoCodeConstant;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * DynamicClassLoader 动态类加载器
 *
 * @author Lilin
 * @date 2016/5/23
 */
public class DynamicClassLoader extends ClassLoader {

    private String classPath;

    public DynamicClassLoader(String classPath, ClassLoader parent) {
        super(parent);
        this.classPath = classPath;
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 判断当前加载的类是否是需要动态重新加载的类,
        // 假如是通过重写的findClass在自定义的ClassLoader里面加载,
        // 假如不是就调用父ClassLoader默认加载
        if (name != null && name.equals(classPath)) {
            return findClass(name);
        }
        return super.loadClass(name, false);
    }

    /**
     * 根据类名查找class
     *
     * @param fullClassPath 类全路径(包)
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String fullClassPath)
            throws ClassNotFoundException {
        byte[] raw = readClassBytes(fullClassPath);
        // definClass方法参数说明:name:类包的全路径如com.lkb.sb.client.shanghaiC.ShangHaiLoginClient
        //                         b:读取的class文件的byte数组
        //                         off:从byte数组中读取的索引
        //                         len:从byte数组中读取的长度
        // 注:假如此类中有引入别的class类,如com.lkb.sb.client.BaseClient,循环执行findClass方法
        Class<?> clazz = defineClass(fullClassPath, raw, 0, raw.length);
        // 连接class
        resolveClass(clazz);
        return clazz;
    }

    /**
     * 读取class
     *
     * @param fullClassPath
     * @return
     */
    private byte[] readClassBytes(String fullClassPath) {
        byte[] raw = null;
        InputStream stream = null;
        try {
            File file = new File(AutoCodeConstant.BASE_PATH + fullClassPath.replaceAll("\\.", "/") + AutoCodeConstant.CLASS_SUFFIX);
            stream = new FileInputStream(file);
            raw = new byte[(int) file.length()];
            stream.read(raw);
        } catch (Exception e) {

        } finally {
            try {
                stream.close();
            } catch (Exception e) {
            }
        }
        return raw;
    }

}

 

 

注:调用方式:

                // 通过自定义类加载器来加载
                // 获取类的完成路径
                String fullClassPath = getFullClassPath(AutoCodeConstant.CLIENT_PACKAGE, provinceCode, cityCode, AutoCodeConstant.LOGIN_CLIENT);
                // 父ClassLoader设为当前线程的ClassLoader,试过使用ClassLoader.getSystemClassLoader(),发现获取的是系统级的,懒加载的类找不到
                dynamicClassLoader = new DynamicClassLoader(fullClassPath, Thread.currentThread().getContextClassLoader());
                loginInterface = (LoginInterface) dynamicClassLoader.loadClass(fullClassPath).getConstructor(new Class[]{CommonLoginSb.class, SbDefultModel.class}).newInstance(new Object[]{commonLoginSb, sbDefultModel});
                // 执行start方法
                resOutput = loginInterface.start(commonLoginSb.getMethod());

 

posted @ 2016-05-26 10:00  GisClub  阅读(11984)  评论(0编辑  收藏  举报