美文网首页springbootkankan(good)Java
从源码角度查看SpringBoot是怎样获取到Bean的

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

作者: 互联网高级架构师 | 来源:发表于2023-02-25 13:47 被阅读0次

    我们都知道在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中的 比较简单 不涉及其他复杂逻辑

    作者:爱喝可乐h
    链接:https://juejin.cn/post/7203620183172382776
    来源:稀土掘金

    相关文章

      网友评论

        本文标题:从源码角度查看SpringBoot是怎样获取到Bean的

        本文链接:https://www.haomeiwen.com/subject/kevfldtx.html