手写热部署+SpringBoot热部署的实现(待续)

自定义Java类加载器来实现Java类的热加载

public class MyClassLoader extends ClassLoader

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

/**
 * 自定义Java类加载器来实现Java类的热加载
 * @author liuyazhuang
 *
 */
public class MyClassLoader extends ClassLoader {
	//要加载的Java类的classpath路径
	private String classpath;
	
	public MyClassLoader(String classpath){
		super(ClassLoader.getSystemClassLoader());//调用父类的构造方法
		this.classpath = classpath;
	}
	
	//要复写的核心方法
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		//下面自定义方法加载class文件中的内容
		byte[] data = this.loadClassData(name);

		//类名,字节数组 ,开始 ,长度
		return this.defineClass(name, data, 0, data.length);
	}

	/**
	 * 加载class文件中的内容
	 * @param name
	 * @return
	 */
	private byte[] loadClassData(String name) {
		try {
			name = name.replace(".", "//");// "." 变成 "//" 
			FileInputStream is = new FileInputStream(new File(classpath + name + ".class"));//文件路径
			ByteArrayOutputStream baos = new ByteArrayOutputStream();//字节数组输出流
			int b = 0;
			while ((b = is.read()) != -1) {
				baos.write(b);
			}
			is.close();
			return baos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
		
}

实现这个接口的子类需要动态更新

/**
 * 实现这个接口的子类需要动态更新
 * @author liuyazhuang
 *
 */
public interface BaseManager {
	public void logic();
}

BaseManager的子类,此类需要实现java类的热加载功能
public class MyManager implements BaseManager {

	@Override
	public void logic() {
		System.out.println("我在慕课网学习呢,我在慕课网上学习了Spring Boot热部署这门课程");
		System.out.println("慕课网学习资源很丰富,师资很强大,学习的人很多");
	}

}


封装加载类的信息

/**
 * 封装加载类的信息
 * @author liuyazhuang
 *
 */
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;
	}
}

加载manager的工厂

/**
 * 加载manager的工厂
 * @author liuyazhuang
 *
 */
public class ManagerFactory {
	//记录热加载类的加载信息
	private static final Map<String, LoadInfo> loadTimeMap = new HashMap<String, LoadInfo>();
	//要加载的类的classpath
	public static final String CLASS_PATH = "D:/Workspaces/muke/classloader/bin/";
	//实现热加载的类的全名称(包名+类名)
	public static final String MY_MANAGER = "com.imooc.classloader.MyManager";
	
	public static  BaseManager getManager(String className){
		File loadFile = new File(CLASS_PATH + className.replaceAll("\\.", "/") + ".class");
		long lastModified = loadFile.lastModified();
		//loadTimeMap不包含className为key的LoadInfo信息。证明这个类没有被加载,那么需要加载这个类到JVM
		if(loadTimeMap.get(className) == null){
			load(className, lastModified);
		}//加载类的时间戳变化了,我们同样要重新加载这个类到JVM
		else if(loadTimeMap.get(className).getLoadTime() != lastModified){	
			load(className, lastModified);
		}
		return loadTimeMap.get(className).getManager();
	}

	private static void load(String className, long lastModified) {
		MyClassLoader myClassLoader = new MyClassLoader(CLASS_PATH);
		Class<?> loadClass = null;
		try {
			loadClass = myClassLoader.loadClass(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		BaseManager manager = newInstance(loadClass);
		LoadInfo loadInfo = new LoadInfo(myClassLoader, lastModified);
		loadInfo.setManager(manager);
		loadTimeMap.put(className, loadInfo);
	}
	//以反射的方式创建BaseManager子类对象
	private static BaseManager newInstance(Class<?> loadClass) {
		try {
			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;
	}
}

后台启动一条线程不断刷新重新加载实现了热加载的类

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) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

测试Java类的热加载

/**

  • 测试Java类的热加载
  • @author liuyazhuang

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

发布了162 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_39088066/article/details/103579214