推测出Main类(main()方法所在的类)
- 从调用栈中去获取main类!
private Class<?> deduceMainApplicationClass() {try {// 获取调用栈数组StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();// 找到调用栈中的main方法!for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())) {return Class.forName(stackTraceElement.getClassName());}}}catch (ClassNotFoundException ex) {// Swallow and continue}return null;}
核心的启动方法:run(String... args)public ConfigurableApplicationContext run(String... args) {// 开始时间long startTime = System.nanoTime();// 创建引导启动器,类似一个ApplicationContext,可以往里面添加一些对象 。DefaultBootstrapContext bootstrapContext = createBootstrapContext();// spring容器对象,开始的时候为空ConfigurableApplicationContext context = null;// 与awt有关,一般用不上configureHeadlessProperty();// spring boot的启动监听器// 从spring.factories中获取SpringApplicationRunListener对象的值// 默认会拿到EventPublishingRunListener,他会启动各个地方的ApplicationEvent事件 。SpringApplicationRunListeners listeners = getRunListeners(args);// 发布开始启动的事件:ApplicationstartingEventlisteners.starting(bootstrapContext, this.mainApplicationClass);try {// 把run方法的参数进行封装ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 准备environment对象:包括操作系统、jvm、ymal、properties....配置// 发布一个ApplicationEnvironmentPreparedEvent事件 。ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 默认spring.beaninfo.ignore为true,表示不需要jdk去缓存BeanInfo信息,spring自己缓存 。// 这里是spring在创建bean的时候会利用jdk的一些工具来解析一个类的相关信息,jdk在解析一个类的信息的时候会进行缓存,这里就是禁止了jdk的缓存 。configureIgnoreBeanInfo(environment);// 打印BannerBanner printedBanner = printBanner(environment);// 根据应用类型,创建spring容器context = createApplicationContext();// jdk9的一个机制,默认没做任何操作context.setApplicationStartup(this.applicationStartup);// 准备容器的操作// 利用ApplicationContextInitializer初始化spring容器// 发布ApplicationContextInitializedEvent(容器初始化完成)事件// 发布BootstrapContextClosedEvent(关闭引导容器)事件// 注册primarySources类(run方法存进来的配置类)// 发布ApplicationPreparedEvent事件prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// refresh容器:解析配置类、扫描、启动webServer 。spring相关的逻辑!refreshContext(context);// 空方法,类似spring的onRefresh方法,可以由子类实现 。afterRefresh(context, applicationArguments);// 启动的事件Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}// 发布一个ApplicationStartedEvent事件,表示spring已经启动完成listeners.started(context, timeTakenToStartup);// 从spring容器中获取ApplicationRunner和CommandLineRunner,并执行他的run方法 。// 这俩个可以自己定义BeancallRunners(context, applicationArguments);}catch (Throwable ex) {// 失败之后,发布一个失败的事件:ApplicationFailedEventhandleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {// 计算下事件Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);// 一切都成功,发布ApplicationStartedEvent事件listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {// 失败之后,发布一个失败的事件:ApplicationFailedEventhandleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 深入理解AQS--jdk层面管程实现【管程详解的补充】
- 如何评价冻鳗高手他爹塔塔酱
- 什么是耕地类型
- 如何解决胸闷气短
- 马来西亚护照怎么办理
- 为中华之崛起而读书读后感
- 酸奶的营养价值及功效
- 台式电脑怎么装系统
- 解释一下蔚然深秀什么意思
- 修改路由器密码必须要用电脑吗