type
status
date
slug
summary
tags
category
icon
password
😀
这里写文章的前言: Spring源码流程阅读
 

📝 阅读方式

  • 创建一个 Maven项目,引入Spring相关的依赖, 然后写一个启动类,在类上打上debug一层一层的走进去,就可以看到源码是怎么走的,怎么加载的
  • 从github上git Spring到自己本来,然后安装gradle,build 一下项目就可以了,这是基于Spring源码去跑的,可以直接在代码里面打印对应的输出语句,对于代码的走向是更加熟悉的
  • 目前比较流行的是SpringBoot,也可以直接启动一个SpringBoot项目,然后在run方法上打上断点,跟着源码一步一步的走,最后每个方法都走一遍会很有效的理解

源码阅读

这里我们写一个读取从包位置扫描的类. 其实这个注解,你也可以加入到你启动类上面去扫描,效果也是一样的.这样的话,YangConfig就会当作为一个bean。如果你写在你的启动类上的话,那么你的启动类就会当作为一个bean
启动类, 可以看到对于启动类,还是做了不少实验,但是这肯定是不够的,启动还是有很多的内容没有完全的写入进去的. 在这里打算断点就可以去跟着源码走。等等,这里是不是少了一个很明显的bean

梦开始的地方

这里我们打上debug,跟着代码一步一步的走进去,看看是如何执行的. 想看想法是怎么走的话,就可以仔细看堆栈的信息。 然后我们跟着开始的方法,一步一步的跟着走进去
org.springframework.context.annotation.AnnotationConfigApplicationContext
 
这里我们跟着 this() 这个构造方法一步一步的走.
new AnnotatedBeanDefinitionReader(this) 走到下面的地方
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(org.springframework.beans.factory.support.BeanDefinitionRegistry)
this.reader = new AnnotatedBeanDefinitionReader(this) 的调用链分析,这里给我的感觉,就是对系统的一些数据,进行创建beanDefinition,然后放入到BeanFactory中去
 
this.scanner = new ClassPathBeanDefinitionScanner(this); 调用链分析org.springframework.context.annotation.ClassPathBeanDefinitionScanner
 

register 方法

走完了 this() 方法就会走register方法, 从名字上可以看出意思,注册。那么 这个地方到底是注册什么呢? 跟着代码继续往下看,到底是在读取些什么
 

refresh方法

refresh() 方法是最主要的方法,这里我们只是使用了 Spring, 到SpringBoot 的源码中, 还是有调用这个refresh 这个方法
可以看到 refresh 方法里面还是走了蛮多的方法. 有一些方法是留给扩展的,比如 onRefresh() 这个方法,当你启动SpringBoot的话,这个方法就会走到去 new Tomcat的逻辑
sychronized 关键字,可以看到进入执行下面的代码,一次只容许一个线程进来操作

prepareRefresh () 方法

org.springframework.context.support.AbstractApplicationContext
可以看到 prepareRefresh 显示对closed和active参数值设置,然后检验一下配置参数,然后是有问题的话,就会抛出异常来。 然后对 earlyApplicationListeners进行判断或者初始化,初始化 earlyApplicationEvents 集合
 

obtainFreshBeanFactory() 方法

 

prepareBeanFactory(beanFactory) 方法

 

postProcessBeanFactory(beanFactory)方法

// 可以看到这个方法,是走到下面的方法,是没有做任何代码. 应该是留到子类进行实现走自己的逻辑
 

invokeBeanFactoryPostProcessors(beanFactory) 方法

 

registerBeanPostProcessors(beanFactory) 方法

从名字上看,是对BeanPostProcessors进行注册
可以总体看到 registerBeanPostProcessors 这个方法,根据BeanPostProcessor获取出postProcessorNames,然后对 postProcessorNames 进行迭代, 进行分类处理,分别装入不同的集合中.对 不同的集合进行先后迭代处理,排序,添加到beanFactory中去. 这里多了 BeanPostProcessorChecker 和 ApplicationListenerDetector这二个,是在这儿给添加进去的
 

initMessageSource() 方法

这个方法,如果beanFactory中是有 MESSAGE_SOURCE_BEAN_NAME 的话,就会进行判断, 都满足条件的话,就会走到hms.setParentMessageSource(getInternalParentMessageSource());这个方法
如果不包含的话,就会去new一个DelegatingMessageSource,然后添加到beanFactory中的bdMap中去
 

initApplicationEventMulticaster() 方法

 

onRefresh():

留给子类扩展的. 比如SpringBoot中,这里就会初始化一些SpringMvc的信息,然后new Tomcat()等
 

regeisterListeners() 方法

这个方法,目前在单纯的Spring中跑起来上面都没有,但是从名字上看的话,目测是对 Listeners进行注册到 beanFactory中去
 

finishBeanFactoryInitializarion() 方法

 

doGetBean() 方法

do开头才是真正做事的方法
走完这个方法,基本一个bean的创建就走完了.可以看出来,这其中的逻辑还是很复杂的.做了各种BeanPostPrcoessor进行扩展,中间还走了一个Aware的接口判断,估摸着也是进行扩展的逻辑
 

doCreateBean() 方法

可以看到这个是真正的create bean的方法
 

finishRefresh方法

 

resetCommonCaches方法

这个方法可以看大是对一个工具类使用的集合进行clear.如果不清除的话,其中有些是再初始化后用不上的,就会浪费内存
 

🤗 总结归纳

📎 参考文章

 
💡
有关文章的问题,欢迎您在底部评论区留言,一起交流~