Java自定义类加载器实现热部署实例
在慕课网上看到这个课程,然后照着视频敲了一遍代码,完全没问题的代码,运行的时候,就是不出现热部署的效果,把我愁死了,后来发现,无论是在eclipse还是在idea中运行,都是需要通过Debug模式运行。这里要实现热加载部署,重点就是需要自定义我们的类加载器,然后监听类的修改时间,如果修改时间发生改变,就将其重新加载到虚拟机中。所有代码如下:MyClassLoader.javapackage com
·
在慕课网上看到这个课程,然后照着视频敲了一遍代码,完全没问题的代码,运行的时候,就是不出现热部署的效果,把我愁死了,后来发现,无论是在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模式。
更多推荐
已为社区贡献23条内容
所有评论(0)