当我们在eclipse中修改了一个.java文件时,并通过【ctrl + s 】保存了此java文件,相应的bin目录中,会发现.class文件也发生了修改。通常情况下,java文件是在我们的web项目已经启动了的情况下进行修改的,而.class文件早已加载至虚拟机中。因 此,在没有使用热部署插件的情况下,必须重启tomcat服务。而热部署插件其原理就是将修改后的.class文件重新加载至jvm中的。

public class Test {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
ClassLoader classLoader = Test.class.getClassLoader();
Class<?> clazz = classLoader.loadClass("com.classloader.Test");
Test test = (com.classloader.Test) clazz.newInstance();
test.logic();
} public void logic() {
System.out.println("hello classloader");   
}
}

1.自定义一个MyClassLoader 类

public class MyClassLoader extends ClassLoader {

    private static final String CLASS_PATH = System.getProperty("java.class.path");    // 编译生成的.class文件的bin目录

    public MyClassLoader() {
super(ClassLoader.getSystemClassLoader());
} @Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
byte[] b = loadClassFile(className);
return super.defineClass(className, b, 0, b.length);
} private byte[] loadClassFile(String className) {
File file = new File(CLASS_PATH + "/" + className + ".class");
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = 0;
while ( (b=fis.read())!=-1 ) {
baos.write(b);
}
fis.close();
return baos.toByteArray();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return null;
} }

2.创建一个工厂类

public class ObjectFactory {

	private static final String CLASS_PATH = System.getProperty("java.class.path");	// 编译生成的.class文件的bin目录
private static Map<String, Object> map = new HashMap<String, Object>();
private static long lastModified; // 最后修改时间 private ObjectFactory() {
super();
} public static Object getInstance(String className) {
File loadFile = new File(CLASS_PATH + "/" + className.replace(".", "/") + ".class"); // 打开项目中bin目录下的*.class文件
long newModified = loadFile.lastModified();
// 文件第一次加载,通过反射的方式创建一个对象
if (map.get(className)==null) {
loadClass(className);
}
// .class 文件被修改过,通过ClassLoader方式 创建一个对象
if (lastModified!=newModified) {
loadClass(className);
}
lastModified = newModified;
return map.get(className);
} private static void loadClass(String className) {
MyClassLoader myClassLoader = new MyClassLoader();
try {
Class<?> clazz = myClassLoader.findClass(className);
Object object = clazz.newInstance();
map.put(className, object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} 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 (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

  

3.定义一个接口,供方法调用【注:这里必须要定义一个接口类,否则会抛出类型转换错误】

public interface PrintService {

    public void print();
}

4.接口的实现类

public class PrintServiceImpl implements PrintService {

    @Override
public void print() {
System.out.println("测试一下 bbb 1111111111");
}
}

5.编写一个用于观察的线程类

public class PrintThread implements Runnable {

    @Override
public void run() {
String className = PrintServiceImpl.class.getName();
// 一直不断地向控制台输出信息,方便测试“当修改print 中的方法时” 输出信息是否发生变化
while (true) {
PrintService printService = (PrintService) ObjectFactory.getInstance(className);
printService.print(); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
public class Test {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Thread thread = new Thread(new PrintThread());
thread.start();
}
}

最新文章

  1. 配置163Yum源自动判断你的系统是Centos版本(适用于5.x或6.x)
  2. CocoaPods看的三篇文章
  3. Android 中Webview 自适应屏幕
  4. ExtJS002Window创建
  5. php导出excel数据
  6. [译] 反思 1 号进程 / Rethinking PID 1
  7. SAP 月结F.19与GR/IR
  8. spring boot 配置 fastjson 替代 Jackson (并解决返回字符串带双引号问题)
  9. [curl]convert curl to python Ruby
  10. WPF DEV gridcontrol 自定义计算列(TotalSummary)
  11. 3,postman的变量写法和collection
  12. navicat 定时备份
  13. 四则运算法则在Java中的实现
  14. Python 函数 (关键字参数)
  15. [Object Tracking] Deep Boundary detection Tech
  16. 【做题】Codeforces Round #453 (Div. 1) D. Weighting a Tree——拆环
  17. vue 导出excel表格
  18. Authentication required (packagist.phpcomposer.com) 账号密码到哪里获取?
  19. Set和Map数据
  20. Druid在有赞的实践

热门文章

  1. 基于mysql数据库集群的360度水平切割
  2. shell script语法高亮和自动缩进的配置
  3. 编程练习赛11B 物品价值(装压dp)
  4. Java子类强制转父类类型不会变
  5. apue.3e源码下载及编译
  6. thrift安装及常见问题
  7. Object有哪些方法?
  8. 分享知识-快乐自己:MYSQL之內链接 左链接 右链接 区别
  9. 微信公众号 iOS UITextFiled 用中文键盘输英文出现空格的解决方法
  10. JS前端重点 -- Generator 函数的含义与用法