springboot流程分析
- 毫无疑问 点击进入SpringApplication.run方法 ,run方法只做了一件事:new SpringApplication(class).run(args);
- 构造方法里面主要是进行一些初始操作,getSpringFactoriesInstances方法是去获取通过SPI机制暴露的接口
- 接着看run方法
run 方法里面有一步很关键的 refreshContext(context)
如何知道是这一步为关键步骤?
上一步为 prepareContext 方法(上下文准备),可以看到context现在还没什么东西
而在refresh后,context可以看到bean
- 很明显 我们的研究的重点在refreshContext方法里面,点进去 一直跟踪到AbstractApplicationContext类的refresh方法里面,可以看到方法加了sync锁 保障refresh时线程安全
- 找到对beanFactory进行操作的方法
AbstractApplicationContext的postProcessBeanFactory方法什么都没做 ,
接下来就是invokeBeanFactoryPostProcessors方法了,点进去看看spring做了什么
6.接下来的步骤比较繁琐 直接说方法名了 不一一截图
invokeBeanFactoryPostProcessors()方法中 第一行代码:
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
点进去找到invokeBeanFactoryPostProcessors方法,
点进去找到postProcessBeanDefinitionRegistry方法,
点进去找到processConfigBeanDefinitions方法,
点进去找到 parser.parse(candidates),
点进去找到 this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
点两步进去找到 sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
点进去找到Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
点进去找到 return scanner.doScan(StringUtils.toStringArray(basePackages));
doScan则是重点,它的findCandidateComponents方法 扫描了我们项目中的component注解类, resource获取class
而isCandidateComponent方法 看起来是在判断是否为Component ,点进去查看一下,注:@services等组件也是被Component 修饰
这一步则比较明显 往set中添加
6. findCandidateComponents结束后 回到doScan
这些正是我们写的被Component 注解修饰的类
- 结束对component的扫描后 我们继续看AbstractApplicationContext类 ,看到finishBeanFactoryInitialization方法
点进去找到 beanFactory.preInstantiateSingletons(); 找到getBean()
如果为单例 则创建bean
- 创建bean 这正是spring bean 的生命周期 —— 实例化
同样在这个doCreateBean方法中,
-
spring bean的生命周期 —— 填充属性
this.populateBean(beanName, mbd, instanceWrapper); -
spring bean 的生命周期 —— 初始化
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
- 最后 则是spring bean的销毁
这里总结一点:refresh() 和 destroy()(或 close())方法都在AbstractApplicationContext类里面,
refresh的invokeBeanFactoryPostProcessors(beanFactory) 扫描了component ,finishBeanFactoryInitialization(beanFactory) 调用 bean创建、填充、初始化方法,
实际对bean的操作 都在beanFactory相关类里面
spring的生命周期
bean的生命周期简述版:实例化,填充属性,初始化,销毁 (当然,这不是大家想听的 接着往下看)
-
BeanDefinition : 扫描bean的定义,例如是否懒加载 ,beanClass信息,scope作用范围等
-
BeanFactoryPostProcessor: BeanFactory的后置处理器 在BeanFactory组建完之后(组建完并不是指所有bean装载完) 可以对beanFactory里面的东西 比如beanDefinition相关属性 进行操作 (beanDefinition就位于beanFactory中)
-
bean的创建 (根据上文提到的beanClass属性去创建)
-
推断构造:
下述第一种情况会涉及到 循环依赖 三级缓存. spring会去判断是否含有@autowired注解 有autowired则使用autowired的构造(最优先) . 使用无参构造(次优先) . 当没有无参构造时,且仅有一个有参构造 使用有参构造 . 当有多个有参构造 且没有无参及autowired时 报错
-
依赖注入(属性填充)(byType byName)
-
Aware (回调)
如果实现了BeanNameAware接口 会执行setBeanName方法,
我们日常开发 博主是没有体会到它实际的使用妙处,毕竟要处理初始化业务逻辑,第7点使用的比较多。
或许是它可以在初始化前就获取beanName 可能在框架设计上需要用到 (通过beanName做其它设计)
-
bean初始化前 (@PostConstruct)
. 例如有一个services层的bean的某个字段 初始就需要通过查询数据库获取值,可以在初始前执行 . 总之可以执行各种初始化前的业务逻辑。
(或者实现InitializingBean接口)
-
bean初始化
-
bean初始后(aop)
-
(存在aop时) 生成代理对象
. 代理对象刚生成的时候 TestProxy extends Test ,属性是没有值的, 这时会找到之前创建的bean . 例如@before注解, 代理Test中的test方法时,会先执行切面代码 再执行test方法
-
(存在aop时)bean为代理对象
-
存放在单例池 (单例池也位于beanFactory)