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 loadTimeMap = new HashMap();
	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();
	}
}

    运行截图:

    Java自定义类加载器实现热部署实例_第1张图片 

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

你可能感兴趣的:(java,classloader,热加载)