阿里Java学习路线:阶段 1:Java语言基础-Java语言高级特性:第25章:ClassLoader类加载器:课时116:自定义ClassLoader处理类

清楚了类加载器的功能之后就可以根据自身的需要来实现自定义的类加载器,但是需要千万要记住一点,自定义的类加载器其加载的顺序是所有系统类加载器的最后。系统类中的类加载器都是根据CLASSPATH路径进行类加载的,而如果有了自定义类的加载器,就可以由开发者任意指派类的加载位置。
在这里插入图片描述
1、随意编写一个程序类,并且将这个类保存在磁盘上。

package cn.mldn.util;
public class Message {
	public void send() {
		System.out.println("www.mldn.cn");
	}
}

2、将此类直接拷贝到D盘上进行编译处理,并且不打包:javac Message.java,此时并没有进行打包处理,所以这个类无法通过CLASSPATH正常加载。
3、自定义一个类加载器,并且继承自ClassLoader类。在ClassLoader类里面为用户提供有一个字节转换为类结构的方法:
定义类:protected final Class<?> defineClass(String name, byte[] b, int off, int len) thorws ClassFormatError;

package cn.mldn.util;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class MLDNClassLoader extends ClassLoader {
	private static final String MESSAGE_CLASS_PATH = "D:" + File.separator + "Message.class";
	/**
	 * 进行指定类的加载
	 * @param className 类的完整名称“包.类”
	 * @return 返回一个指定类的Class对象
	 * @throws Exception 如果类文件不存在则无法加载
	 */
	public Class<?> loadData(String className) throws Exception {
		byte [] data = this.loadClassDate(); // 读取二进制数据文件
		if (data != null) { // 读取到了
			return super.defineClass(className, data, 0, data.length) ;
		}
		return null ;
	}
	private byte [] loadClassDate() throws Exception { // 通过文件进行类的加载
		InputStream input = null ;
		ByteArrayOutputStream bos = null ; // 将数据加载到内存之中
		byte data [] = null ;
		try {
			bos = new ByteArrayOutputStream() ; // 实例化内存流
			input = new FileInputStream(new File(MESSAGE_CLASS_PATH)); // 文件流加载
			input.transferTo(bos); // 读取数据
			data = bos.toByteArray(); // 将所以读取到的字节数据取出		
		} catch (Exception e) {
			
		} finally {
			if (input != null) {
				input.close();
			}
			if (bos != null) {
				bos.close();
			}
		}
		return data;
	}
}

4、编写测试类实现类加载控制。

package cn.mldn.demo;
import java.lang.reflect.Method;
import cn.mldn.util.MLDNClassLoader;
class Message {}
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
    	MLDNClassLoader classLoader = new MLDNClassLoader(); // 实例化自定义加载器
    	Class<?> cls = classLoader.loadData("cn.mldn.util.Message"); // 进行类的加载
    	Object obj = cls.getDeclaredConstructor().newInstance();
    	Method method = cls.getDeclaredMethod("send");
    	method.invoke(obj);
    }
}

如果在以后结合到网络程序开发的话,就可以通过一个远程的服务器来确定类的功能。
在这里插入图片描述
5、观察当前的Message类的加载器的情况。

package cn.mldn.demo;
import cn.mldn.util.MLDNClassLoader;
class Message {}
public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
    	MLDNClassLoader classLoader = new MLDNClassLoader(); // 实例化自定义加载器
    	Class<?> cls = classLoader.loadData("cn.mldn.util.Message"); // 进行类的加载
    	System.out.println(cls.getClassLoader());
    	System.out.println(cls.getClassLoader().getParent());
    	System.out.println(cls.getClassLoader().getParent().getParent());
    }
}

程序执行结果:
cn.mldn.util.MLDNClassLoader@312b1dae
jdk.internal.loader.ClassLoaders$AppClassLoader@119d7047
jdk.internal.loader.ClassLoaders$PlatformClassLoader@3941a79c

如果说你现在定义了一个类,这个类的名字为:java.lang.String,并且利用了自定义的类加载进行加载处理,这个类将不会被加载,java之中针对于类加载器提供有双亲加载机制,如果现在要加载的程序类是由系统提供的类则会由系统类进行加载,如果现在开发者定义的类与系统类名称相同,那么为了保证系统的安全性绝对不会加载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值