5.2:缓存中获取单例bean
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的更多相关文章
- Spring源码分析(十三)缓存中获取单例bean
摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 介绍过FactoryBean的用法后,我们就可以了解bean加载的过程了 ...
- Spring IOC 容器源码分析 - 获取单例 bean
1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...
- Spring框架中的单例bean是线程安全的吗?
不,Spring框架中的单例bean不是线程安全的.
- Spring 框架中的单例 bean 是线程安全的吗?
不,Spring 框架中的单例 bean 不是线程安全的.
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...
- Spring IOC(三)单例 bean 的注册管理
Spring IOC(三)单例 bean 的注册管理 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 在 Spring 中 ...
- Spring源码分析(十五)获取单例
本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例be ...
- Spring(六)核心容器 - 注册单例 Bean 实例、SingletonBeanRegistry 简介
前言 上篇文章我们对注册 Bean 的核心类 BeanDefinitionRegistry 进行了讨论,这里的注册 Bean 是指保存 Bean 的相关信息,也就是将 Bean 定义成 BeanDef ...
- Spring 获取单例流程(一)
读完这篇文章你将会收获到 在 getBean 方法中, Spring 处理别名以及 factoryBean 的 name Spring 如何从多级缓存中根据 beanName 获取 bean Spri ...
随机推荐
- Jersey(1.19.1) - JSON Support
Jersey JSON support comes as a set of JAX-RS MessageBodyReader<T> and MessageBodyWriter<T&g ...
- MyBatis(3.2.3) - Dynamic SQL
Sometimes, static SQL queries may not be sufficient for application requirements. We may have to bui ...
- Ajax B/S 聊天工具txt文件保存
打算做一个两个或多个网页之间交流的功能,思路是多个页面聊天的内容存放到一个文件里,每个页面都有提交聊天功能,当提交聊天信息时保存到上面那个文件里, 在每个也页面里放一个定时器,每秒钟获取聊天文件里的记 ...
- 让.NET程序会说话
在开发过程中需要用到让程序自动播放语音,如果是一个一个录则太麻烦了,在开发过程中发现.NET已经自带了该功能 Type type = Type.GetTypeFromProgID("SAPI ...
- (转)实战Memcached缓存系统(4)Memcached的CAS协议
1. 什么是CAS协议 很多中文的资料都不会告诉大家CAS的全称是什么,不过一定不要把CAS当作中国科学院(China Academy of Sciences)的缩写.Google.com一下,CAS ...
- 【leetcode】365. Water and Jug Problem
题目描述: You are given two jugs with capacities x and y litres. There is an infinite amount of water su ...
- 开启Windows的索引服务
除开SearchEverything电脑内部的全硬盘搜索之外,如果要搜索文件内的内容的话,就无能为力的了.Window内置的索引服务就派上用场了,这么好的服务,默认设置居然是关闭的,想不通. 下面来介 ...
- 《RedHatlinux系统修复(通过FTP进行修复)》
比如我们删除了grub文件的initrd然后我们来修复 Linux系统下装的虚拟机boot options 位置,我们选网络修复,提前是我已经做好了ftpbootlaoder的配置. Win系统下以V ...
- js中的等号与非等号
等号与非等号都会进行类型转换,转换规则如下: 1 如果有一个是boolean值,则true改为1,false改为0 false == 0 ; true == 1 返回true true == 2 ...
- C#委托的异步调用1
本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: /*添加的命名空间 u ...