今天调试的时候,发现了一个令我震惊的功能,不知道是不是我孤陋寡闻了,但是这个功能我觉得实在是太变态了
众所周知,在Idea进入断点的时候,可以加载内存中类实例
这里可以搜索到我们想要找的实例对象 比如有一个controller
@RestController
public class TestController {
@GetMapping("/testC")
public String test(){
long l = System.currentTimeMillis();
System.out.println(l);
return String.valueOf(l);
}
}
右键 Show Instances
然后再右键你想选择的实例 评估表达式
这个时候我们就可以看到,评估窗口自动填充了一个对象(没有展开点击右上角展开按钮)
如果我们输入一个 . ,神奇的事情发生了,我们可以直接用这个实例!What Fxxx! 竟然可以从内存中取任意一个实例并且随手拿来用??
甚至可以在这里面调用静态方法,写局部变量,点击评估就可以显示最后一个变量的结果,就相当随时更改 随时编译并且保持上下文变量不变的一个方法体???如果断点在一个方法,还使用方法的局部变量,这个功能太变态了,我甚至以为自己在浏览器里写JS而不是java
然而,还有更变态的用法:
当在一个实例上点击“评估表达式”时,固然会带出这个实例的变量,但是如果想要同时获取多个实例,目前的方法就不行了,点击两个实例评估,就会出现两个评估窗口,但是两个评估窗口之间的实例并不共享
聪明的同学想必已经知道怎么办了,我们可以使用一个静态Map将这个实例引用存下来然后再另一处地方取出来!
public class TestController {
static Map<String,Object> objectMap = new HashMap<>();
public static void putObject(String key, Object value) {
objectMap.put(key,value);
}
public static Object get(String key) {
return objectMap.get(key);
}
}
点击评估,将对象存入map
然后在另外一个窗口取用:
这样就可以随时拿到任何变量了,真心感觉这个功能很强大,不知道为什么Idea没有继续开发,如果把这个开发成一个随时拿任何实例,随时跑任何方法,不用重启Spring 也不用反复修改编译的专门的功能,估计就要乐死了
不过目前的功能已经很强大了,特别是调试不了解的API,只要改一改点一下评估就能在同一个上下文反复一键运行,实在是太方便了,开发效率真的直线提升
另外附赠一个小技巧,如果想要随时进断点,用评估测试代码,但是每次都要用postman什么的发起,可以试试这个:
@Configuration(proxyBeanMethods = false)
//记得把这个类放入git的.gitignore 不然上传到生产库可就炸了
//小项目也可以用`@Profile("dev")`只让它在指定环境生效
public class DebugConfig {
@PostConstruct
void thread() {
Thread thread1 = getThread1();
thread1.start();
Thread thread2 = getThread2(new ThreadProxy(thread1));
thread2.start();
}
Thread getThread1() {
return new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException ignored) {
}
}, "01断点线程");
}
Thread getThread2(ThreadProxy thread1) {
return new Thread(() -> {
while (true) {
if (!thread1.getThread().isAlive()) {
System.out.println("砸瓦鲁多"); //断点打在这里
thread1.setThread(getThread1());
thread1.getThread().start();
}
}
}, "02观察线程");
}
@Data
@AllArgsConstructor
static class ThreadProxy {
private Thread thread;
}
}
然后在线程窗口,中断断点线程就会自动进入砸瓦鲁多断点,随时随地进入断点,配合评估非常方便