皮皮网

皮皮网

【php 商店源码】【opengl 源码目录】【junit 源码解析】springgetbean源码

时间:2024-12-28 20:44:06 分类:百科

1.Spring IoC:getBean 详解
2.Spring源码-09-Bean工厂之getBean方法
3.Spring 中 个getBean 的作用

springgetbean源码

Spring IoC:getBean 详解

       接着 Spring IoC:finishBeanFactoryInitialization 详解,我们正式开始学习获取 bean 实例方法,该方法是 Spring 最核心的方法。

       单击 preInstantiateSingletons 方法里的 getBean(beanName) 代码,进入该方法。

       见 doGetBean 方法详解。php 商店源码

       doGetBean

       1.解析 beanName,主要是解析别名、去掉 FactoryBean 的修饰符 “&”,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块4已解析过。

       2.尝试从缓存中获取 beanName 对应的实例,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块7已解析过。

       3.1 返回 beanName 对应的实例对象(主要用于 FactoryBean 的特殊处理,普通 bean 会直接返回 sharedInstance 本身),见代码块1详解。

       6.如果不是仅仅做类型检测,而是创建 bean 实例,这里要将 beanName 放到 alreadyCreated 缓存,见代码块5详解。opengl 源码目录

       7.根据 beanName 重新获取 MergedBeanDefinition,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块2已解析过。

       8.2 检查 dep 是否依赖于 beanName,即检查是否存在循环依赖,见代码块6详解。

       8.4 将 dep 和 beanName 的依赖关系注册到缓存中,见代码块7详解。

       9.1 scope 为 singleton 的 bean 创建(新建了一个 ObjectFactory,并且重写了 getObject 方法),见代码块8详解。

       9.1.1、9.2.2、9.3.4 创建 bean 实例,限于篇幅,在下篇文章单独解析。

       9.1.2、9.2.4、9.3.6 返回 beanName 对应的junit 源码解析实例对象,见代码块1详解。

       9.2.1 scope 为 prototype 时创建实例前的操作、9.2.3 scope 为 prototype 时 创建实例后的操作,相对应的两个方法,见代码块详解。

       代码块1:getObjectForBeanInstance

       如果对 FactoryBean 不熟悉的,可以回头去看 Spring IoC:finishBeanFactoryInitialization 详解 中对 FactoryBean 的简单介绍。

       6.mbd 为空,但是该 bean 的 BeanDefinition 在缓存中存在,则获取该 bean 的 MergedBeanDefinition,在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块2已经解析过。

       8.从 FactoryBean 获取对象实例,见代码块2详解。

       代码块2:getObjectFromFactoryBean

       3.调用 FactoryBean 的 getObject 方法获取对象实例,见代码块3详解。

       5.对 bean 实例进行后续处理,执行所有已注册的 BeanPostProcessor 的 postProcessAfterInitialization 方法,见代码块4详解。springcloud 源码 pdf

       代码块3:doGetObjectFromFactoryBean

       很简单的方法,就是直接调用 FactoryBean 的 getObject 方法来获取到对象实例。

       细心的同学可以发现,该方法是以 do 开头,看过 Spring IoC:源码总览 的同学知道,我在总览里就特别提到以 do 开头的方法是最终进行实际操作的方法,例如本方法就是 FactoryBean 最终实际进行创建 bean 对象实例的方法。

       代码块4:postProcessObjectFromFactoryBean

       这边走的是 AbstractAutowireCapableBeanFactory 里的方法。通过前面的介绍,我们知道创建的 BeanFactory 为 DefaultListableBeanFactory,而 DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory,因此这边会走 AbstractAutowireCapableBeanFactory 的重写方法。

       在 Spring IoC:registerBeanPostProcessors 详解 中已经学过 BeanPostProcessor,在创建完 bean 实例后,会执行 BeanPostProcessor 的 postProcessAfterInitialization 方法。

       代码块5:markBeanAsCreated

       2.这边会将 beanName 对应的 MergedBeanDefinition 移除,然后在之后的代码重新获取,主要是bomb lab源码为了使用最新的 MergedBeanDefinition 来进行创建操作。

       代码块6:isDependent

       这边引入了一个缓存 dependentBeanMap:beanName -> 所有依赖 beanName 对应的 bean 的 beanName 集合。内容比较简单,就是检查依赖 beanName 的集合中是否包含 dependentBeanName,隔层依赖也算。例如:A 依赖了 B,B 依赖了 C,则 A 也算依赖了 C。

       代码块7:registerDependentBean

       这边又引入了一个跟 dependentBeanMap 类似的缓存,dependenciesForBeanMap:beanName -> beanName 对应的 bean 依赖的所有 bean 的 beanName 集合。

       这两个缓存很容易搞混,举个简单例子:例如 B 依赖了 A,则 dependentBeanMap 缓存中应该存放一对映射:其中 key 为 A,value 为含有 B 的 Set;而 dependenciesForBeanMap 缓存中也应该存放一对映射:其中 key 为:B,value 为含有 A 的 Set。

       代码块8:getSingleton

       5.创建单例前的操作,7.创建单例后的操作,这两个方法是对应的,见代码块9详解。

       6.执行 singletonFactory 的 getObject 方法获取 bean 实例,该方法会走文章开头 doGetBean 方法的注释 9.1.1。

       8.如果是新的单例对象,将 beanName 和对应的单例对象添加到缓存中,见代码块详解。

       代码块9:beforeSingletonCreation、afterSingletonCreation

       inCreationCheckExclusions 是要在创建检查排除掉的 beanName 集合,正常为空,可以不管。这边主要是引入了 singletonsCurrentlyInCreation 缓存:当前正在创建的 bean 的 beanName 集合。在 beforeSingletonCreation 方法中,通过添加 beanName 到该缓存,可以预防出现构造器循环依赖的情况。

       为什么无法解决构造器循环依赖?

       我们之前在 Spring IoC:finishBeanFactoryInitialization 详解 中的代码块7提过,getSingleton 方法是解决循环引用的核心代码。解决逻辑的第一句话:“我们先用构造函数创建一个 “不完整” 的 bean 实例”,从这句话可以看出,构造器循环依赖是无法解决的,因为当构造器出现循环依赖,我们连 “不完整” 的 bean 实例都构建不出来。Spring 能解决的循环依赖有:通过 setter 注入的循环依赖、通过属性注入的循环依赖。

       代码块:addSingleton

       代码块:beforePrototypeCreation、afterPrototypeCreation

       该方法和代码块9的两个方法类似。主要是在进行 bean 实例的创建前,将 beanName 添加到 prototypesCurrentlyInCreation 缓存;bean 实例创建后,将 beanName 从 prototypesCurrentlyInCreation 缓存中移除。这边 prototypesCurrentlyInCreation 存放的类型为 Object,在只有一个 beanName 的时候,直接存该 beanName,也就是 String 类型;当有多个 beanName 时,转成 Set 来存放。

       总结

       本文介绍了获取 bean 实例的大部分内容,包括先从缓存中检查、 FactoryBean 的 bean 创建、实例化自己的依赖(depend-on 属性)、创建 bean 实例的前后一些标记等,在下篇文章中,将解析创建 bean 的内容。

       推荐阅读

Spring源码--Bean工厂之getBean方法

       Bean实例化与管理是Spring框架的核心功能之一,其中getBean方法作为获取Bean实例的主要手段,具有重要意义。接下来,我们将深入探讨getBean方法及其相关实现,以期更好地理解Spring Bean工厂的工作机制。

       一、getBean方法

       getBean方法是Spring容器对外提供的一种接口,用于根据指定的Bean名称获取对应Bean实例。该方法会根据配置信息和缓存机制,找到并返回所需的Bean。

       二、doGetBean方法

       doGetBean方法是getBean方法的内部实现,负责处理Bean的查找、创建和返回工作。其流程分为以下几个关键步骤:

       1. getSingleton

       若Bean是单例且已存在,则直接返回缓存的实例,无需重新创建。

       2. createBean

       若非单例或未找到缓存实例,将进入创建Bean的流程。此过程涉及实例化、属性填充和初始化三个主要步骤。

       2.1 实例化

       通过调用对应的构造函数或使用默认构造函数创建Bean实例。

       2.2 三级缓存

       在实例化后,新创建的Bean会首先存储于缓存中,随后被添加到Bean作用域的缓存中,以备后续使用。

       2.3 属性填充

       通过依赖注入或属性设置方法填充Bean的属性值,确保其具有所需的功能。

       2.4 初始化

       执行Bean的初始化方法,实现任何特定的初始化逻辑,如配置文件加载或数据库连接等。

       三、流程图

       为了更直观地展示getBean方法的执行流程,以下流程图详细展示了从查找至返回Bean实例的全过程,包括缓存操作、实例化、属性填充和初始化等关键步骤。

       四、循环依赖示意图

       在处理循环依赖时,Spring容器会采取特定策略以避免无限循环。以下示意图展示了两个单例Bean(A和B)之间循环依赖的处理过程,以及Spring如何通过延迟初始化等机制解决这一问题。

       本文通过深入剖析getBean方法及其相关实现,旨在帮助开发者更好地理解Spring Bean工厂的工作机制。通过掌握这些关键概念与流程,可以更高效地利用Spring框架构建可维护且高性能的应用程序。

Spring 中 个getBean 的作用

       getBean是用来获取applicationContext.xml文件里bean的,()写的是bean的id。

       ä¸€ç§æ˜¯singleton,一种是prototype,默认的是singleton,这种定义的bean实例的作用是与spring的容器一致的,只有spring容器初始化,调用getBean得到的singleton实例始终是同一个bean的实例spring定义的bean有两种作用范围,是每当调用getBean得到实例的时候spring都会new一个实例来给你,而prototype的实例。