Java自定义类加载器实现热部署实例

    在慕课网上看到这个课程,然后照着视频敲了一遍代码,完全没问题的代码,运行的时候,就是不出现热部署的效果,把我愁死了,后来发现,无论是在eclipse还是在idea中运行,都是需要通过Debug模式运行。

    这里要实现热加载部署,重点就是需要自定义我们的类加载器,然后监听类的修改时间,如果修改时间发生改变,就将其重新加载到虚拟机中。

    所有代码如下:

    MyClassLoader.java

package com.xxx.classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;

public class MyClassLoader extends ClassLoader{
	private String classpath;
	public MyClassLoader(String classpath ) {
		super(ClassLoader.getSystemClassLoader());
		this.classpath = classpath;
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] data = this.loadClassData(name);
		
		return this.defineClass(name, data, 0, data.length);
	}

	private byte[] loadClassData(String name) {
		try {
			name = name.replace(".", "//");
			FileInputStream is = new FileInputStream(new File(classpath+name+".class"));
			int b = 0;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while((b=is.read())!=-1) {
				baos.write(b);
			}
			is.close();
			return baos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

    BaseManager.java

package com.xxx.classloader;

public interface BaseManager {
	public void logic();
}

    MyManager.java

package com.xxx.classloader;

public class MyManager implements BaseManager {

	@Override
	public void logic() {
		System.out.println("i am testing hotreload,hello.");
	}

}

    LoadInfo.java

package com.xxx.classloader;

public class LoadInfo {
	private MyClassLoader myLoader;
	private long loadTime;
	private BaseManager manager;
	public LoadInfo(MyClassLoader myLoader, long loadTime) {
		//super();
		this.myLoader = myLoader;
		this.loadTime = loadTime;
	}
	public MyClassLoader getMyLoader() {
		return myLoader;
	}
	public void setMyLoader(MyClassLoader myLoader) {
		this.myLoader = myLoader;
	}
	public long getLoadTime() {
		return loadTime;
	}
	public void setLoadTime(long loadTime) {
		this.loadTime = loadTime;
	}
	public BaseManager getManager() {
		return manager;
	}
	public void setManager(BaseManager manager) {
		this.manager = manager;
	}
	
}

    ManagerFactory.java 

package com.xxx.classloader;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class ManagerFactory {
	private static final Map<String, LoadInfo> loadTimeMap = new HashMap<String, LoadInfo>();
	private static final String CLASS_PATH = "D:/eclipse/workspaces/classloader/bin/";
	public static final String MY_MANAGER = "com.xxx.classloader.MyManager";
	public static BaseManager getManager(String className) {
		File loadFile = new File(CLASS_PATH+className.replaceAll("\\.", "/") + ".class");
		long lastModified = loadFile.lastModified();
		System.out.println("current class loadtime -> "+lastModified);
		if(loadTimeMap.get(className) == null) {
			load(className,lastModified);
		}else if(loadTimeMap.get(className).getLoadTime() != lastModified) {
			load(className,lastModified);
		}
		
		return loadTimeMap.get(className).getManager();
	}
	private static void load(String className, long lastModified) {
		// TODO Auto-generated method stub
		MyClassLoader myClassLoader = new MyClassLoader(className);
		Class<?> loadClass = null;
		try {
			loadClass = myClassLoader.loadClass(className);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		BaseManager manager = newInstance(loadClass);
		LoadInfo loadInfo = new LoadInfo(myClassLoader, lastModified);
		loadInfo.setManager(manager);
		loadTimeMap.put(className, loadInfo);
	}
	private static BaseManager newInstance(Class<?> loadClass) {
		// TODO Auto-generated method stub
		try {
			System.out.println("load...");
			return (BaseManager)loadClass.getConstructor(new Class[] {}).newInstance(new Object[] {});
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
	
}

    MsgHandler.java

package com.xxx.classloader;

public class MsgHandler implements Runnable{
	@Override
	public void run() {
		while(true) {
			BaseManager manager = ManagerFactory.getManager(ManagerFactory.MY_MANAGER);
			manager.logic();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

    ClassLoaderTest.java

package com.xxx.classloader;

public class ClassLoaderTest {
	public static void main(String[] args) {
		new Thread(new MsgHandler()).start();
	}
}

    运行截图:

     

    这篇博客的重点不在于代码本身,因为我写这篇博客也特意在网上搜索了一下,发现cnblog上已经有人把代码给贡献出来,而且还给了很详细的注解。我这里要强调的是 要实现自定义类加载器实现热部署的效果,我们需要运行在Debug模式。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值