我们要分析一个框架的源码不可能通过一篇文章就搞定的,本文我们就来分析下springboot源码中的主线流程。先掌握springboot项目启动的核心操作,然后我们再深入每一个具体的实现细节,注:本系列源码都以springboot2.2.5.relea版本来讲解
当我们启动一个springboot项目的时候,入口程序就是main方法,而在main方法中就执行了一个run方法。
@springbootapplicationpublic class startapp {public static void main(string[] args) {springapplication.run(startapp.class);}}
然后我们进入run()方法中看。代码比较简单
public static configurableapplicationcontext run(class<?> primarysource, string... args) {// 调用重载的run方法,将传递的class对象封装为了一个数组return run(new class<?>[] { primarysource }, args);}
调用了重载的一个run()方法,将我们传递进来的类对象封装为了一个数组,仅此而已。我们再进入run()方法。
public static configurableapplicationcontext run(class<?>[] primarysources, string[] args) {// 创建了一个springapplication对象,并调用其run方法// 1.先看下构造方法中的逻辑// 2.然后再看run方法的逻辑return new springapplication(primarysources).run(args);}
在该方法中创建了一个springapplication对象。同时调用了springapplication对象的run方法。这里的逻辑有分支,先看下springapplication的构造方法中的逻辑
我们进入springapplication的构造方法,看的核一氧化碳燃烧的化学方程式心代码为
public springapplication(resourceloader resourceloader, class<?>... primarysources) {// 传递的resourceloader为nullthis.resourceloader = resourceloader;asrt.notnull(primarysources, "primarysources must not be null");// 记录主方法的配置类名称this.primarysources = new linkedhasht<>(arrays.aslist(primarysources));// 记录当前项目的类型this.webapplicationtype = webapplicationtype.deducefromclasspath();// 加载配置在spring.factories文件中的applicationcontextinitializer对应的类型并实例化// 并将加载的数据存储在了 i炖汤大全nitializers 成员变量中。tinitializers((collection) getspringfactoriesinstances(applicationcontextinitializer.class));// 初始化监听器 并将加载的监听器实例对象存储在了listeners成员变量中tlisteners((collection) getspringfactoriesinstances(applicationlistener.class));// 反推main方法所在的class对象 并记录在了mainapplicationclass对象中this.mainapplicationclass = deducemainapplicationclass();}
在本方法中完成了几个核心操作
1.推断当前项目的类型
2.加载配置在spring.factories
文件中的applicationcontextinitializer
中的类型并实例化后存储在了initializers中。
3.和2的步骤差不多,完成监听器的初始化操作,并将实例化的监听器对象存储在了listeners成员变量中
4.通过stacktrace反推main方法所在的class对象
上面的核心操作具体的实现细节我们在后面的详细文章会给大家剖析
接下来我们在回到springapplication.run()方法中。
public configurableapplicationcontext run(string... args) {// 创建一个任务执行观察器stopwatch stopwatch = new stopwatch();// 开始执行记录执行时间stopwatch.start();// 声明 configurableapplicationcontext 对象configurableapplicationcontext context = null;// 声明集合容器用来存储 springbootexceptionreporter 启动错误的回调接口collection<springbootexceptionreporter> exceptionreporters = new arraylist<>();// 设置了一个名为java.awt.headless的系统属性// 其实是想设置该应用程序,即使没有检测到显示器,也允许其启动.//对于服务器来说,是不需要显示器的,所以要这样设置.configureheadlessproperty();// 获取 springapplicationrunlistener 加载的是 eventpublishingrunlistener// 获取启动时到监听器springapplicationrunlisteners listeners = getrunlisteners(args);// 触发启动事件listeners.starting();try {// 构造一个应用程序的参数持有类applicationarguments applicationarguments = new defaultapplicationarguments(args);// 创建并配置环境configurableenvironment environment = prepareenvironment(listeners, applicationarguments);// 配置需要忽略的beaninfo信息configureignorebeaninfo(environment);// 输出的banner信息b国庆小报anner printedbanner = printbanner(environment);// 创建应用上下文对象context = createapplicationcontext();// 加载配置的启动异常处理器exceptionreporters = getspringfactoriesinstances(springbootexceptionreporter.class,new class[] { configurableapplicationcontext.clasc罗简介资料s }, context);// 刷新前操作preparecontext(context, environment, listeners, applicationarguments, printedbanner);// 刷新应用上下一笑倾人城文 完成spring容器的初始化refreshcontext(context);// 刷新后操作afterrefresh(context, applicationarguments);// 结束记录启动时间stopwatch.stop();if (this.logstartupinfo) {new startupinfologger(this.mainapplicationclass).logstarted(getapplicationlog(), stopwatch);}// 事件广播 启动完成了listeners.started(context);callrunners(context, applicationarguments);}catch (throwable ex) {// 事件广播启动出错了handlerunfailure(context, ex, exceptionreporters, listeners);throw new illegalstateexception(ex);}try {// 监听器运行中listeners.running(context);}catch (throwable ex) {handlerunfailure(context, ex, exceptionreporters, null);throw new illegalstateexception(ex);}// 返回上下文对象--> spring容器对象return context;}
在这个方法中完成了springboot项目启动的很多核心的操作,我们来总结下上面的步骤
创建了一个任务执行的观察器,统计启动的时间声明configurableapplicationcontext
对象声明集合容器来存储springbootexceptionreporter
即启动错误的回调接口设置java.awt.headless
的系统属性获取我们之间初始化的监听器(eventpublishingrunlistener
),并触发starting事件创建applicationarguments
这是一个应用程序的参数持有类创建configurableenvironment
这时一个配置环境的对象配置需要忽略的beaninfo
信息配置banner信息对象创建对象的上下文对象加载配置的启动异常的回调异常处理器刷新应用上下文,本质就是完成spring容器的初始化操作启动结束记录启动耗时完成对应的事件广播返回应用上下文对象。到此springboot项目的启动初始化的代码的主要流程就介绍完成了。细节部分后面详细讲解。
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注www.887551.com的更多内容!
本文发布于:2023-04-04 08:17:22,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/d0f3eaf5789a29a76f287f718e9a22b6.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Java SpringBoot核心源码详解.doc
本文 PDF 下载地址:Java SpringBoot核心源码详解.pdf
留言与评论(共有 0 条评论) |