内容简介:在《在进行main方法的推断时,主要使用了堆栈信息一层层的判断,来获得main方法。具体源代码如下:基本流程就是创建一个运行时异常,然后获得堆栈数组,遍历StackTraceElement数组,判断方法名称是否为“mian”,如果过是则通过Class.forName()方法创建Class对象。
在《 SpringBoot源码解析之应用类型识别 》一文中我们已经了解了SpringBoot是如何推断出应用类型的。在推断出应用类型之后,SpringBoot又进行了main方法的推断。
在进行main方法的推断时,主要使用了堆栈信息一层层的判断,来获得main方法。具体源代码如下:
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
} catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
基本流程就是创建一个运行时异常,然后获得堆栈数组,遍历StackTraceElement数组,判断方法名称是否为“mian”,如果过是则通过Class.forName()方法创建Class对象。
代码很简单,但是SpringBoot的使用方法是否让我们觉得很有启发性呢。下面对照一下 Java 的异常处理,具体了解一下StackTrace的使用。
Stacktrace(堆栈跟踪)是一个非常有用的调试工具。在程序出现异常或手动抛出异常时,可以显示出出错的地方,引起错误的层级关系。
当我们try,catch到异常时,可以通过printStackTrace()方法将堆栈信息打印出来。也可以通过日志框架将相关信息输出到日志文件中。
这里通过一个单元测试来真切体验一下SpringBoot是这段代码的过程。
public class StackTraceTest {
@Test
public void testStackTrace(){
RuntimeException exception = new RuntimeException();
StackTraceElement[] traceElements = exception.getStackTrace();
for(StackTraceElement element : traceElements){
System.out.println(element.getClassName() + ":" + element.getMethodName());
}
throw exception;
}
}
上面代码创建一个RuntimeException异常,并获得StackTraceElement数组,将其启动的className和methodName打印出来。最后,再将异常抛出。我们来对比,打印的日志与抛出异常的日志是否一致。
System.out.println打印的日志信息:
com.secbro2.learn.utils.StackTraceTest:testStackTrace sun.reflect.NativeMethodAccessorImpl:invoke0 sun.reflect.NativeMethodAccessorImpl:invoke sun.reflect.DelegatingMethodAccessorImpl:invoke java.lang.reflect.Method:invoke org.junit.runners.model.FrameworkMethod$1:runReflectiveCall org.junit.internal.runners.model.ReflectiveCallable:run org.junit.runners.model.FrameworkMethod:invokeExplosively org.junit.internal.runners.statements.InvokeMethod:evaluate org.junit.runners.ParentRunner:runLeaf org.junit.runners.BlockJUnit4ClassRunner:runChild org.junit.runners.BlockJUnit4ClassRunner:runChild org.junit.runners.ParentRunner$3:run org.junit.runners.ParentRunner$1:schedule org.junit.runners.ParentRunner:runChildren org.junit.runners.ParentRunner:access$000 org.junit.runners.ParentRunner$2:evaluate org.junit.runners.ParentRunner:run org.junit.runner.JUnitCore:run com.intellij.junit4.JUnit4IdeaTestRunner:startRunnerWithArgs com.intellij.rt.execution.junit.IdeaTestRunner$Repeater:startRunnerWithArgs com.intellij.rt.execution.junit.JUnitStarter:prepareStreamsAndStart com.intellij.rt.execution.junit.JUnitStarter:main
异常抛出的信息:
java.lang.RuntimeException
at com.secbro2.learn.utils.StackTraceTest.testStackTrace(StackTraceTest.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
对比会发现,它们的顺序、类、方法,完全一致。
方法很简单,功能也很简单,但通过读源代码,竟然发现SpringBoot将我们日常视而不见的内容竟然用出新的花样。或许这就是读源代码的魅力所在吧。
以上所述就是小编给大家介绍的《SpringBoot源码解析之main方法推断》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Java8 新语法习惯 (类型推断)
- JDK11 | 第三篇 : 局部变量类型推断
- Java 10推断类型和var关键字简介
- C# 8 的新提案:new 关键字类型推断
- PMD 6.4.0 发布,支持 Java 10 局部变量类型推断
- Java 10 - 与“var类型推断机制”的第一次亲密接触
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Cracking the Coding Interview
Gayle Laakmann McDowell / CareerCup / 2015-7-1 / USD 39.95
Cracking the Coding Interview, 6th Edition is here to help you through this process, teaching you what you need to know and enabling you to perform at your very best. I've coached and interviewed hund......一起来看看 《Cracking the Coding Interview》 这本书的介绍吧!