• Spring源码里开天辟地的五个Bean,再介绍一个学习方法


                                        准备工作

    首先咱们还是来写一个最简单的例子:

    用的还是 https://github.com/xiexiaojing/yuna 里的代码,只是标签和引用都换成了Spring原生的。

    配置类就是配置了扫描路径:

    在可以被扫描的包路径下定义了一个Bean对象。用了Component注解这里就可以理解为Bean对象了。

    运行成功,通过Spring的IoC容器成功的获取了UserService的Bean对象,并调用了其test方法。

    在《把对象交给spring管理的3种方法及经典应用》中我提到Spring有5个开天辟地的Bean。还列出了怎么通过SpringBoot的debug去找。这里其实在debug日志里就能看到把它们打印出来了:

    ​大家不要忽略启动日志,读懂启动日志能获得很多信息,今天咱们就把这段启动日志Spring相关的部分分析透。

                           Spring启动日志第一行

    org.springframework.context.annotation.AnnotationConfigApplicationContext

    -

    Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5bfbf16f

    上面是Spring日志的第一行,翻译成中文就是刷新注解配置应用上下文。咱们来看源码:

    进入这个实例化方法中看Spring的源码:

    共三行,咱们来解读一下:

    this初始化方法,里面初始化的后面都要用到,用到的时候再看,这一行可以忽略。剩余两行,一行作用是注册Bean的定义,另外一行是完成Bean的定义。

    先时候注册Bean的定义。什么叫Bean的定义呢。如果Bean是一个产品,那Bean定义就是它的规格说明书。就是一个文档说明,这时候Bean还没有开始创建。注册Bean定义还有一种通过扫描来实现的方式:

    这时候进入Spring注解配置应用上下文的实例化方法变成这个:

    ​第二行register方法变成scan方法,其他没有变化,这说明scan方法和register方法完成了两种的功能。就是BeanDefinition。scan的原理我在《手撕spring核心源码,彻底搞懂spring流程》里详细讲过,这就和之前的内容对上了。

    创建的事情要交给Bean工厂,也就是refresh方法要做的事情。

    其实Bean工厂能不能完成Bean的创建等生命周期管理呢?可以。咱们的测试例子也可以这么写:

    ​我直接用Bean工厂创建一个Bean也能实现。那ApplicationContext应用上下文与BeanFactory的区别在哪里呢?

    BeanFactory可以理解为一个汽车工厂,它就是生产汽车的。 别人需要告诉他汽车怎么生产,看我例子里BeanDeclaration实际有很多参数需要我来添上,我展开给大家看看:

    ApplicationContext 可以理解为汽车4s店。他提供一条龙服务。我只需要告诉他,我需要哪个汽车,其他都不需要管了。4s店自己帮我处理好。

    咱们来看refresh方法,synchronized是多线程同步的,不需要管。第一个运行的方式是prepareRefresh。

    ​进入这个方法就找到了第一行日志打印的地方:

    咱们来看prepareRefresh主要做的4件事情:

    1、初始化占位符属性的资源

    2、检验所有必需的属性都是可解析的

    3、存储应用监听器或者应用监听器半成品

    4、初始化应用事件半成品

    ​这四件事情不是本文的核心内容仅做了解。其实这四件事情对下文没有任何推动作用,这就是源码存在太多细枝末节,容易干扰视线的原因。所以要带着明确的目的去看。

                              Spring启动日志第二行

    org.springframework.beans.factory.support.DefaultListableBeanFactory

    -

    Creating

    shared

    instance

    of

    singleton

    bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'

    这是Spring开天辟地的五个Bean中的第一个。类型是

    ConfigurationClassPostProcessor

    它是一个BeanFactory的后置处理器,因此它的主要功能是参与BeanFactory的建造,在这个类中,会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解。

    找一行日志打印的位置有点困难,咱们用debug的方式找到哪一行打印的。最终定位在这里:

    下面咱们站在上帝视角重新回到refresh方法:

    refresh的前面都是在组建Bean工厂,从533行也就是内部会打印咱们这条日志的这一行开始调用Bean工厂后置处理器。Bean工厂后置处理器与Bean后置处理器不是一回事。Bean工厂后置处理器的作用就是前面Bean工厂组建完成,现在可以把组建好的Bean工厂传给这个后置处理器。后置处理器自己可以决定要对Bean工厂做些什么。

    因为最重要的方法都在这里面,咱们直接来看

    PostProcessorRegistrationDelegate

    里面做了什么

    ​日志是从标红的那行代码打印的,这是触发实现了高优先级的

    BeanDefinitionRegistryPostProcessor

    进行实例化并注册成后置处理的类。从这里咱们可以得出结论:Spring给它排了很高的优先级,对于Spring默认来说配置类解析器是最先被加载的后置处理器。

                          Spring启动日志第三行

    org.springframework.context.annotation.ClassPathBeanDefinitionScanner

    -

    Identified

    candidate

    component

    class:

    file [D:\yuna\target\classes\com\brmayi\yuna\newspring\UserService.class]

    这是验证用户bean是否符合要求的,可debug查看不详细解释。

    Spring其他4个开天辟地的Bean

    其他的由于方法相同,这里只介绍其他4个Bean的作用:

    EventListenerMethodProcessor和 DefaultEventListenerFactory

    DefaultEventListenerFactory是一个Bean工厂,

    EventListenerMethodProcessor 是 Bean工厂的一个后置处理器, 用来对 @EventListener 提供支持。

    AutowiredAnnotationBeanPostProcessor

    使用Spring 编程时,使用Ioc,我们只需要声明对象,而由Spring 替我门自动注入,

    而其中起重要作用则为

    AutowiredAnnotationBeanPostProcessor,

    它在bean实例化后,进行这重要的初始化操作。

    CommonAnnotationBeanPostProcessor

    这个Bean后置处理器通过继承

    InitDestroyAnnotationBeanPostProcessor

    对@ javax.annotation.PostConstruct

    和@ javax.annotation.PreDestroy

    注解的支持。以及依据bean name依赖注入的

    @javax.annotation.Resource支持。

    总结

    本文介绍了使用查日志所在位置的方式学习源码。这种方式在文中我也特意举例说明了容易被带偏,偏离重心,要做好时间和学习规划,才能达到好的效果。

    学习Spring不是一件容易的事,我之前学习的时候放弃过很多次。这期间不断变换学习方法重新学。最终突然达到了“蓦然回首”的顿悟。从此再看Spring都不是事儿。

    从那之后再也不会因为手欠升级了某个版本或者删除了某些理论上不相关的依赖,程序运行不起来各种尝试才搞定。而变成了遇到问题,呆呆的想上一小会,定位一段源码验证一下猜想,做个简单的调整就搞定了。

    假期哪里也去不了,在家看了一些过去的高分电影。很多电影反映了一些底层贫苦人民暗无天日的生活,一直到最后,他们的生活仍然没有一丝希望。咱们现在可能会经历一些小的痛苦,比如学Spring就很苦,但是这是带着希望的苦。喝下之后就像咖啡一样回味悠远~

  • 相关阅读:
    线程练习题
    前端页面实现【矩阵表格与列表】
    hive笔记(六):分区表和分桶表-分区/二级分区/抽样查询/动态分区调整
    MySQL高级SQL语句
    开发者研究与洞察
    Mysql存储-EAV模式
    fundamental notes in 3D math
    学习java的第十八天。。。(子类)
    马踏棋盘算法 贪心算法优化
    TikTok生态圈【6.28跨境日报】埃及建筑材料和珠宝出口在四个月内大幅增长
  • 原文地址:https://blog.csdn.net/Java_zhujia/article/details/127934194