从源码角度查看SpringBoot是怎样获取到Bean的

背景:

我们都知道在SpringBoot启动类上添加@SpringBootApplication注解后执行main方法就可以自动启动服务 Spring会自动帮我们找到需要管理的Bean的呢

探究:

经典的八股文AbstractApplicationContext#refresh()方法 相信大家已经比较熟悉了

  • 进入invokeBeanFactoryPostProcessors()调用BeanFactory后置处理器方法

  • 进入PostProcessorRegistrationDelegate的invokeBeanDefinitionRegistryPostProcessors方法 注意此方法执行后registry参数(BeanDefinitionRegistry)中的beanDefinitionMap会扫描到需要的bean信息 说明此方法才是真正起到扫描作用的地方 重点!!!

  • 继续进 兄弟们 往里进 ConfigurationClassPostProcessor#processConfigBeanDefinitions 两张图都是此方法 ps:代码太长 其中的这个parser.parse()就是真正解析的方法

  • ConfigurationClassParser#doProcessConfigurationClass到了 很近了 你要问我 我只能说 快到顶了 仔细的同学应该已经看出来了 图上的这个Set会获取@ComponentScan类扫描注解 而这个入参即为我们的启动类Class 其中启动注解@SpringBootApplication中正包含了@CompentScan这个注解 所以此时这个Set中获取到了我们的启动类 红线标注的这个地方继续走哦

  • componentScanAnnotationParser#parse中的scanner.doScan(StringUtils.toStringArray(basePackages)) 这里说明一下这个basePackages由于我们没有指定 所以默认是启动类所在的包路径 ps:这也是需要将启动类放到最外层包的原因 放里面的话无法扫描到对应Bean

ClassPathBeanDefinitionScanner#doScan 继续往里 还是那句 红线标注的地方

ClassPathScanningCandidateComponentProvider#scanCandidateComponents 好了 到站 请各位乘客下车吧 这个方法就是真实找到底层bean的地方 原理很简单 参数basePackage为我们的包根路径 即启动类所在的路径 假设为com/juejin/drink 那么此方法会递归调用扫描com/juejin/drink下的所有类和目录 如果是需要注册的bean 那么放入new的LinkedHashSet中返回

  • 经过如上步骤 程序会返回到PostProcessorRegistrationDelegate的invokeBeanDefinitionRegistryPostProcessors方法继续执行 但此时我们的目的达到了 实际上SpringBoot就是通过@SpringBootApplication的@CompentScan注解 拿到启动类的包路径 最终去递归调用 获取到哪些是我们标注了@Compent这些需要注册进容器的 此步骤是refresh方法的invokeBeanFactoryPostProcessors()中执行的

结语:

本文只是简单的叙述了下Spring是如何将我们的Bean加载到beanDefinitionMap中的 比较简单 不涉及其他复杂逻辑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值