5.2  缓存中获取单例bean

介绍过FactoryBean的用法后,我们就可以了解bean加载的过程了。前面已经提到过,单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上

 public Object getSingleton(String beanName) {
//参数true设置标识允许早期依赖
return getSingleton(beanName, true);
} protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//如果为空,则锁定全局变量并进行处理
synchronized (this.singletonObjects) {
//如果此bean正在加载则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
ObjectFactory singletonFactory = this.singletonFactories.get (beanName);
if (singletonFactory != null) {
//调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
//记录在缓存中,earlySingletonObjects和singletonFactories互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

  这个方法因为涉及循环依赖的检测,以及涉及很多变量的记录存取,所以让很多读者摸不着头脑。这个方法首先尝试从singletonObjects里面获取实例,如果获取不到再从earlySingleton Objects里面获取,如果还获取不到,再尝试从singletonFactories里面获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject来创建bean,并放到earlySingleton Objects里面去,并且从singletonFacotories里面remove掉这个ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在allowEarlyReference为true的情况下才会使用。

这里涉及用于存储bean的不同的map,可能让读者感到崩溃,简单解释如下。

 singletonObjects:用于保存BeanName和创建bean实例之间的关系,bean name --> bean instance。

 singletonFactories:用于保存BeanName和创建bean的工厂之间的关系,bean name --> ObjectFactory。

 earlySingletonObjects:也是保存BeanName和创建bean实例之间的关系,与singletonObjects的不同之处在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用。

 registeredSingletons:用来保存当前所有已注册的bean。

5.2:缓存中获取单例bean的更多相关文章

  1. Spring源码分析(十三)缓存中获取单例bean

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 介绍过FactoryBean的用法后,我们就可以了解bean加载的过程了 ...

  2. Spring IOC 容器源码分析 - 获取单例 bean

    1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...

  3. Spring框架中的单例bean是线程安全的吗?

    不,Spring框架中的单例bean不是线程安全的.

  4. Spring 框架中的单例 bean 是线程安全的吗?

    不,Spring 框架中的单例 bean 不是线程安全的.

  5. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  6. Spring IOC(三)单例 bean 的注册管理

    Spring IOC(三)单例 bean 的注册管理 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 在 Spring 中 ...

  7. Spring源码分析(十五)获取单例

    本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例be ...

  8. Spring(六)核心容器 - 注册单例 Bean 实例、SingletonBeanRegistry 简介

    前言 上篇文章我们对注册 Bean 的核心类 BeanDefinitionRegistry 进行了讨论,这里的注册 Bean 是指保存 Bean 的相关信息,也就是将 Bean 定义成 BeanDef ...

  9. Spring 获取单例流程(一)

    读完这篇文章你将会收获到 在 getBean 方法中, Spring 处理别名以及 factoryBean 的 name Spring 如何从多级缓存中根据 beanName 获取 bean Spri ...

随机推荐

  1. 单击改变input的边框颜色

    input边框变色   今天布局页面的时候发现设计稿多了一项要求,就是点击input框的时候要求框框变色,以前没有遇到过,平时很多时候都用的:hover这次想着一样吧,看了之后发现不是想要的效果,ho ...

  2. Lombok(1.14.8) - @NonNull

    @NonNull @NonNull,生成一个非空检查. package com.huey.lombok; import lombok.Getter; import lombok.NonNull; im ...

  3. ASP常用函数表

    ASP常用函数表(新手们的好工具) 作者:未知 Array() 函数返回一个数组 表达式 Array(list) 允许数据类型: 字符,数字均可 实例: <% Dim myArray() For ...

  4. Android之点击切换图片

    package com.example.SlidePictures; import java.util.Timer; import java.util.TimerTask; import com.ex ...

  5. UIDynamic 基础认识

    UIDynamic 是从iOS 7开始引入的一种新技术,属于UIKit框架,可以模拟现实生活中的物理现象,如:碰撞.抖动.摆动等 动力效果:有一个效果器,叫做“动力效果器”里面面可以添加“动力效果” ...

  6. C#判断输入的是否是汉字

    第一种方法:正则表达式 string text = "是不是汉字"; for (int i = 0; i < text.Length; i++) { if (Regex.Is ...

  7. Smarty控制foreach输出数量

    最近在搞ecshop,ecshop用的是smarty.在首页中想要修改展示的商品数量,但是用的是foreach,让我无从下手,在网上找了好久终于找到解决方案. <!--{foreach name ...

  8. WINDOWS2008 设置FTP防火墙规则

    在防火墙入站规划这里,加上21.20两个端口. 然后重启ftp服务,cmd命令:net stop ftpsvc & net start ftpsvc(重启ftp服务) 一定要重启ftp服务,不 ...

  9. 【译】 Node.js v0.12的新特性 -- Cluster模式采用Round-Robin负载均衡

    原文:https://strongloop.com/strongblog/whats-new-in-node-js-v0-12-cluster-round-robin-load-balancing 本 ...

  10. 【leetcode】363. Max Sum of Rectangle No Larger Than K

    题目描述: Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the ma ...