【spring】spring bean的生命周期 springboot工作原理

springboot流程分析

  1. 毫无疑问 点击进入SpringApplication.run方法 ,run方法只做了一件事:new SpringApplication(class).run(args);
    在这里插入图片描述
  2. 构造方法里面主要是进行一些初始操作,getSpringFactoriesInstances方法是去获取通过SPI机制暴露的接口
  3. 接着看run方法
    run 方法里面有一步很关键的 refreshContext(context)
    如何知道是这一步为关键步骤?
    上一步为 prepareContext 方法(上下文准备),可以看到context现在还没什么东西
    在这里插入图片描述
    而在refresh后,context可以看到bean
    在这里插入图片描述
  4. 很明显 我们的研究的重点在refreshContext方法里面,点进去 一直跟踪到AbstractApplicationContext类的refresh方法里面,可以看到方法加了sync锁 保障refresh时线程安全
    在这里插入图片描述
  5. 找到对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 注解修饰的类

  1. 结束对component的扫描后 我们继续看AbstractApplicationContext类 ,看到finishBeanFactoryInitialization方法
    在这里插入图片描述

点进去找到 beanFactory.preInstantiateSingletons(); 找到getBean()

在这里插入图片描述
在这里插入图片描述

如果为单例 则创建bean
在这里插入图片描述

  1. 创建bean 这正是spring bean 的生命周期 —— 实例化
    在这里插入图片描述
    在这里插入图片描述

同样在这个doCreateBean方法中,

  1. spring bean的生命周期 —— 填充属性
    this.populateBean(beanName, mbd, instanceWrapper);

  2. spring bean 的生命周期 —— 初始化
    exposedObject = this.initializeBean(beanName, exposedObject, mbd);

在这里插入图片描述

  1. 最后 则是spring bean的销毁
    在这里插入图片描述
    这里总结一点:refresh() 和 destroy()(或 close())方法都在AbstractApplicationContext类里面,
    refresh的invokeBeanFactoryPostProcessors(beanFactory) 扫描了component ,finishBeanFactoryInitialization(beanFactory) 调用 bean创建、填充、初始化方法,
    实际对bean的操作 都在beanFactory相关类里面

spring的生命周期

bean的生命周期简述版:实例化,填充属性,初始化,销毁 (当然,这不是大家想听的 接着往下看)

  1. BeanDefinition : 扫描bean的定义,例如是否懒加载 ,beanClass信息,scope作用范围等

  2. BeanFactoryPostProcessor: BeanFactory的后置处理器 在BeanFactory组建完之后(组建完并不是指所有bean装载完) 可以对beanFactory里面的东西 比如beanDefinition相关属性 进行操作 (beanDefinition就位于beanFactory中)
    在这里插入图片描述

  3. bean的创建 (根据上文提到的beanClass属性去创建)

  4. 推断构造:
    下述第一种情况会涉及到 循环依赖 三级缓存

     . spring会去判断是否含有@autowired注解 有autowired则使用autowired的构造(最优先)
     . 使用无参构造(次优先)
     . 当没有无参构造时,且仅有一个有参构造 使用有参构造
     . 当有多个有参构造 且没有无参及autowired时 报错
    

在这里插入图片描述

  1. 依赖注入(属性填充)(byType byName)

  2. Aware (回调)
    如果实现了BeanNameAware接口 会执行setBeanName方法,
    我们日常开发 博主是没有体会到它实际的使用妙处,毕竟要处理初始化业务逻辑,第7点使用的比较多。
    或许是它可以在初始化前就获取beanName 可能在框架设计上需要用到 (通过beanName做其它设计)
    在这里插入图片描述

  3. bean初始化前 (@PostConstruct)

     . 例如有一个services层的bean的某个字段 初始就需要通过查询数据库获取值,可以在初始前执行
     . 总之可以执行各种初始化前的业务逻辑。
    

    (或者实现InitializingBean接口)

  4. bean初始化

  5. bean初始后(aop)

  6. (存在aop时) 生成代理对象

    . 代理对象刚生成的时候 TestProxy extends Test ,属性是没有值的, 这时会找到之前创建的bean
    . 例如@before注解, 代理Test中的test方法时,会先执行切面代码 再执行test方法
    
  7. (存在aop时)bean为代理对象

  8. 存放在单例池 (单例池也位于beanFactory)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟秋与你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值