自定义类加载器

什么时候需要类加载器?

  • 想加载非classpath随意路径中的类文件
  • 都是通过接口来实现,希望解耦时候,常用在框架设计
  • 这些类希望予以隔离,不同应用的同类名都可以加载,不冲突

步骤

  • 1.继承ClassLoader父类
  • 2.要遵从双亲委派机制,重写findClass方法
    注意不是重写loadClass,否则不会走双亲委派的机制
  • 3.读取类文件的字节码
  • 4.调用父类的defineClass方法来加载类
  • 5.使用者调用类加载器器的loadClass方法

需求与实现

我们自己约定的需求如下,我们从外部路径/tmp/myclasspath/加载类

具体实现如下:

public class MyClassLoader extends ClassLoader{ //继承ClassLoader父类
    /**
     * name就是类名称
     */
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String path="/tmp/myclasspath/"+name+".class";
        System.out.println("path:"+path);
        ByteArrayOutputStream os=new ByteArrayOutputStream();
        try {
            Files.copy(Paths.get(path),os);
            byte[] bytes=os.toByteArray();

            //byte[] -> *.class
            return  defineClass(name,bytes,0,bytes.length);//父类中的defineClass加载,如果找不到会调用本类的defineClass进行加载
        } catch (IOException e) {
            e.printStackTrace();
            throw new ClassNotFoundException("类文件未找到",e);
        }
    }
}

代码测试:

 public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader classLoader=new MyClassLoader();
        Class<?> c1=classLoader.loadClass("HelloWorld");
        Class<?> c2=classLoader.loadClass("HelloWorld");
        System.out.println(c1==c2);
        c1.newInstance();
        //System.out.println(c1.newInstance());
    }

我们在路径下面定义下类:
在这里插入图片描述
运行结果:

true

小总结

  • 自定义加载类的需求主要来自需要从外部加载类运行的时候,我们很常见的场景就是Tomcat的lib类,还有类似rpc调用的时候,类的实现有时候是从网络中传输过来的
  • 双亲委派的机制其实就是一个递归调用的机制,父类先寻找加载的类,如若没有找到,则用当前类加载器去加载,这个的结果就是,如果提前加载过了,则不会在继续被加载,保证了类的版本一致性
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值