自定义类加载器(一)

一.概述

1.自定义类加载器时需要继承ClassLoader,并且重写其findClass()方法

2.具体实现过程:

①定义类加载器的加载路径属性

②通过带参构造为属性赋值

③重写findClass()

1>确定class文件的全路径,并启动字节流读取class文件

2>创建ByteArrayOutputStream用于将字节流读入至字节数组中

*****数据将写入缓冲区中,缓冲区随着数据的写入会自动增长

3>使用byte[] classData接收字节数组并判断字节数组是否为null

4>若classData为null,则说明该类文件未被加载,亦说明该类文件不能被找到,则抛出ClassNotFoundException

5>若classData不为空,则调用defineClass创建该类文件的对象

二.代码实现

1.被加载class文件对应类的定义(TargetTest.java)

/**
 * @author :weihuanwen
 * @date :Created in 2019/5/23 00:14
 * @description :
 * @version: 1.0
 */
public class TargetTest {
    /**
     * 重写toString方法
     * 类加载器加载该类class文件后可以创建该类对象
     * 使用对象可以调用该toString方法
     * @return
     */
    @Override
    public String toString() {
        return "Hi! You find me!";
    }
}

在java文件所在目录下使用javac -encoding UTF-8 TargetTest.java可以将其编译为class文件

2.自定义类加载器代码实现(CustomClassLoader.java)

import java.io.*;

/**
 * @author :weihuanwen
 * @date :Created in 2019/5/23 00:14
 * @description :自定义File类加载器
 * @version: 1.0
 */
public class CustomClassLoader extends ClassLoader{
    //类加载器加载类文件范围
    private String rootDir;

    public CustomClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    /**
     * 重写ClassLoader的findClass方法
     * ①读取class文件通过字节流写入字节数组
     * ②调用defineClass将字节数组转为class对象
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //拼接class文件的全路径
        String classFilePath = rootDir+ File.separator+name.replace(".",File.separator)+ ".class";
        try {
            //字节流读取class文件
            InputStream is = new FileInputStream(classFilePath);
            //该字节流可以将数据写入字节数组,数据写入缓冲区时缓冲区自动增长
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[4096];
            int length = 0;
            //读取类文件并写入字节数组中
            while ((length = is.read(bytes))!= -1){
                baos.write(bytes,0,length);
            }
            //获取类文件的字节数组
            byte[] classData = baos.toByteArray();
            if (classData == null){
                throw new ClassNotFoundException();
            }else{
                return defineClass(name, classData,0,classData.length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

3.测试类定义(CustomClassLoaderTest.java)

/**
 * @author :weihuanwen
 * @date :Created in 2019/5/23 00:14
 * @description :
 * @version: 1.0
 */
public class CustomClassLoaderTest {
    //测试自定义的类加载器
    public static void main(String[] args) {
        String root = "D:\\study\\";
        //创建指定搜索路径的自定义类加载器对象
        CustomClassLoader ccl = new CustomClassLoader(root);
        try {
            Class<?> demoObj = ccl.loadClass("TargetTest");
            System.out.println(demoObj.newInstance().toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试结果输出:

Hi! You find me!

三.自定义类加载器实现热加载

1.修改测试类结构:

import java.util.Timer;
import java.util.TimerTask;
/**
 * @author :weihuanwen
 * @date :Created in 2019/5/23 00:14
 * @description :
 * @version: 1.0
 */
public class test {
    public static void main(String[] args) {
        //设置定时任务
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                String rootPath = "D:\\study\\";
                CustomDefineLoader cdl = new CustomDefineLoader(rootPath);
                try {
                    Class<?> targetTest = cdl.loadClass("TargetTest");
                    System.out.println(targetTest.newInstance().toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },0,1001);
    }
}

2.将TargetTest.java放置在D:\study文件夹中

3.在CMD命令框中将TargetTest.java编译为TargetTest.class文件

输入:

4.执行测试类CustomClassLoaderTest.java

执行结果如下:

5.程序运行过程中修改TargetTest.java文件

/**
 * @author :weihuanwen
 * @date :Created in 2019/5/23 00:14
 * @description :
 * @version: 1.0
 */
public class TargetTest {
    /**
     * 重写toString方法
     * 类加载器加载该类class文件后可以创建该类对象
     * 使用对象可以调用该toString方法
     * @return
     */
    @Override
    public String toString() {
        return "GoodBye!";
    }
}

6.将修改后的文件再次进行编译,生成新的TargetTest.class文件

打印结果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值