深入理解Java类加载器(一):Java类加载原理解析之网络加载器

2、网络类加载器
 下面将通过一个网络类加载器来说明如何通过类加载器来实现组件的动态更新。即基本的场景是:Java 字节代码(.class)文件存放在服务器上,客户端通过网络的方式获取字节代码并执行。当有版本更新的时候,只需要替换掉服务器上保存的文件即可。通过类加载器可以比较简单的实现这种需求。

 类 NetworkClassLoader负责通过网络下载Java类字节代码并定义出Java类。它的实现与FileSystemClassLoader类似。

package classloader;  

import java.io.ByteArrayOutputStream;  
import java.io.InputStream;  
import java.net.URL;  

public class NetworkClassLoader extends ClassLoader {  

    private String rootUrl;  

    public NetworkClassLoader(String rootUrl) {  
        // 指定URL  
        this.rootUrl = rootUrl;  
    }  

// 获取类的字节码  
@Override  
protected Class<?> findClass(String name) throws ClassNotFoundException {  
    byte[] classData = getClassData(name);  
    if (classData == null) {  
        throw new ClassNotFoundException();  
    } else {  
        return defineClass(name, classData, 0, classData.length);  
    }  
}  

private byte[] getClassData(String className) {  
    // 从网络上读取的类的字节  
    String path = classNameToPath(className);  
    try {  
        URL url = new URL(path);  
        InputStream ins = url.openStream();  
        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        int bufferSize = 4096;  
        byte[] buffer = new byte[bufferSize];  
        int bytesNumRead = 0;  
        // 读取类文件的字节  
        while ((bytesNumRead = ins.read(buffer)) != -1) {  
            baos.write(buffer, 0, bytesNumRead);  
        }  
        return baos.toByteArray();  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
    return null;  
}  

private String classNameToPath(String className) {  
    // 得到类文件的URL  
    return rootUrl + "/"  
            + className.replace('.', '/') + ".class";  
    }  
}  

 在通过NetworkClassLoader加载了某个版本的类之后,一般有两种做法来使用它。第一种做法是使用Java反射API。另外一种做法是使用接口。需要注意的是,并不能直接在客户端代码中引用从服务器上下载的类,因为客户端代码的类加载器找不到这些类。使用Java反射API可以直接调用Java类的方法。而使用接口的做法则是把接口的类放在客户端中,从服务器上加载实现此接口的不同版本的类。在客户端通过相同的接口来使用这些实现类。我们使用接口的方式。示例如下:

客户端接口:

package classloader;  

public interface Versioned {  

    String getVersion();  
}  

==========

package classloader;  

public interface ICalculator extends Versioned {  

    String calculate(String expression);  
}  

网络上的不同版本的类:

package com.example;  

import classloader.ICalculator;  

public class CalculatorBasic implements ICalculator {  

    @Override  
    public String calculate(String expression) {  
        return expression;  
    }  

    @Override  
    public String getVersion() {  
        return "1.0";  
    }  
} 

=============

package com.example;  

import classloader.ICalculator;  

public class CalculatorAdvanced implements ICalculator {  

    @Override  
    public String calculate(String expression) {  
        return "Result is " + expression;  
    }  

    @Override  
    public String getVersion() {  
        return "2.0";  
    }  
} 

在客户端加载网络上的类的过程:

package classloader;  

public class CalculatorTest {  

    public static void main(String[] args) {  
        String url = "http://localhost:8080/ClassloaderTest/classes";  
        NetworkClassLoader ncl = new NetworkClassLoader(url);  
        String basicClassName = "com.example.CalculatorBasic";  
        String advancedClassName = "com.example.CalculatorAdvanced";  
        try {  
            Class<?> clazz = ncl.loadClass(basicClassName);  // 加载一个版本的类  
            ICalculator calculator = (ICalculator) clazz.newInstance();  // 创建对象  
            System.out.println(calculator.getVersion());  
            clazz = ncl.loadClass(advancedClassName);  // 加载另一个版本的类  
            calculator = (ICalculator) clazz.newInstance();  
            System.out.println(calculator.getVersion());  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值