源码解析记录springboot注入bean的源码过程
springboot启动类,只要一行代码就启动了,后续完全不需要管理。
进入springApplication.run方法里,简单看看源码:
一步步解析,跳过复杂的先看主过程,首先就是第一行和最后一行:
// 第一行创建启动计时器,用于记录应用启动时间Startup startup = Startup.create();// 最后一行,记录应用启动完成的时间Duration timeTakenToStarted = startup.started();// 如果配置了记录启动信息,则打印启动日志if (this.properties.isLogStartupInfo()) { new StartupInfoLogger(this.mainApplicationClass, environment).logStarted(getApplicationLog(), startup);}
这个很简单,就是启动一个计时的,用于计算springboot启动时候耗时,也就是每个人都见过的,用于看springboot是否启动成功的这个日志:
INFO [main] MyApplication: Started MyApplication in 6.156 seconds (process running for 6.945)
之所以可以用于标识是否启动成功,是因为输出日志的地方位于最后几行了,图片里可以看到输出日志后,下面的就是几个通知,不会影响启动过程。如果启动过程有报错,则会直接进入下面的catch。就不会打印启动完成日志了。
有很多的配置类,先跳过,只看文章的重点,bean的初始化,顺着往下找,在refreshContext中。
可以看到,spring一开始添加了几个类,从入口类,以及spring本身的几个类,作为入口,寻找这些类的下级。
spring为了准确以及严格的顺序,初始化的时候并不是我想的很优雅的一个方法就遍历找出所有的bean初始化。而是分了好几块处理,多次遍历,也多次用了Set列表检测重复。看来越是大型复杂的系统就越是有弯弯绕绕的复杂逻辑
先使用order排序,然后调用处理器遍历所有bean,这是处理的总体思路
继续往下看代码:找到里面的processConfigBeanDefinitions方法:
可以看到,在MyApplication中一次循环就找了185个类出来,包括项目里自己写的类也是在这里初始化的。
通过一个do{}while循环直到为空再也没有下级类了为止
总结:底层代码一开始看着很绕,很多设计模式,慢慢看还是可以看懂的