• 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());
  • 相关阅读:
    Delphi xe8 FMX StringGrid根据内容自适应列宽。
    Delphi 10.3.1 Secure File Sharing解决应用间文件共享
    分享一个求时间差大于多少秒的函数
    解决android 9上无法使用http协议
    【转】FMX 动态创建及销毁(释放free)对象
    ChinaCock界面控件介绍-TCCBarcodeCreator
    IDE Fix Pack 6.4.4 released (bugfix release)
    Android & iOS 启动画面工具
    REST easy with kbmMW #24 使用kbmMW实现JSON/XML/YAML转换成对象
    关于ElasticSearch的聚类时出现fielddata=true问题
  • 原文地址:https://www.cnblogs.com/gisblogs/p/5529953.html
Copyright © 2020-2023  润新知