初始化bean(二)—— 缓存部分

上一篇博客,讲了下spring如何初始化bean的 当然,当时只讨论了很简单的一种情况:初次加载bean时候,并且只考虑了单例。

这篇博客会试着理清楚spring在加载bean的时候的一部分缓存。关于解决循环引用所使用的缓存,可以看这篇博客

从doGetBean开始

首先再次回到doGetBean方法

上一篇博客里,我对doGetBean进行了简化,省略了很多多例及第二次加载相关的代码。

现在想下,如果让我们业务上使用缓存会怎么做。
1)先从缓存查下有没有所需数据
2)没有的话从db加载
3)加载后存到缓存里

缓存的用法无非是这样。spring也是这样使用的。

getSingleton方法

现在再来回顾getSingleton方法就很清楚了

这里我会把流程再简化下,去掉那些扩展的,异常处理等

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "'beanName' must not be null");synchronized (this.singletonObjects) {//先试着从缓存中加载Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {//异常检查 ... //...beforeSingletonCreation(beanName);boolean newSingleton = false;//异常记录...try {//调用ObjectFactory的getObject生成这个对象singletonObject = singletonFactory.getObject();newSingleton = true;}// 省略了异常处理finally{//....afterSingletonCreation(beanName);}if (newSingleton) {//添加到缓存里addSingleton(beanName, singletonObject);}}return (singletonObject != NULL_OBJECT ? singletonObject : null);}
}

这样看就非常清楚了
1)从singleObjects试着找下对应的对象
2)从singletonFactory里创建对象
3)添加到缓存中

和我们平常使用缓存的方式没有任何不同

addSingleton记录缓存

看doGetBean方法,让我感到很晕的地方就是,各种各样缓存。(好多hashMap)而addSingleton方法就是操作缓存的一部分入口。

protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}
}

这里我们先挑看得懂的来分析。

Map<String, Object> singletonObjects 存放了 beanName -> 创建出来的对象
Set<String> registeredSingletons 存放了已注册的单例对象

好像就这两个看得懂哦(~ ̄▽ ̄)~ 没事我们继续分析下去

回到doGetBean开头

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {final String beanName = transformedBeanName(name);Object bean;Object sharedInstance = getSingleton(beanName);//.....
}

doGetBean一开始就试图通过getSingleton方法获取对应的bean
我们再回头看下getSinglteton方法

protected Object getSingleton(String beanName, boolean allowEarlyReference) {//已创建的对象里面找下Object singletonObject = this.singletonObjects.get(beanName);//没找到,并且当前类正在被创建if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

第一行很熟悉,从已加载的对象的缓存里找下。
第二行判断,从方法名很容易猜到意思。只有当从缓存里找不到,并且当前类正在被创建才会走到里面的逻辑。

看下isSingletonCurrentlyInCreation方法

public boolean isSingletonCurrentlyInCreation(String beanName) {return this.singletonsCurrentlyInCreation.contains(beanName);
}

这里又出现了一个不认识的缓存 = =

Set<String> singletonsCurrentlyInCreation

从变量名,很容易猜到是记录当前单例是否正在被创建。

我们跟下往这个set里添加 值的地方。插入值的地方就在getSingleton里的beforeSingletonCreation 这一步里。
之前分析getSingleton方法时,我关注的是如何创建bean,如何使用singletonObjects缓存的。
其实在创建bean前,与创建bean后,有两个方法用于做些前置以及后置处理。分别是beforeSingletonCreationafterSingletonCreation方法。

我们看下这两个方法里都做了啥

创建bean的前置与后置处理

protected void beforeSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}
}protected void afterSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");}
}

这里又出现了两个缓存 inCreationCheckExclusionssingletonsCurrentlyInCreation

inCreationCheckExclusions这个我们先不管,到了这里singletonsCurrentlyInCreation就很清楚了,spring会在创建一个单例对象之前,记录到singletonsCurrentlyInCreation里,在创建完后,从singletonsCurrentlyInCreation里删除。

Set<String> singletonsCurrentlyInCreation 当前正在创建的beanName

回到getSingleton方法

if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

到了这里我有几个问题:
1)为啥getSingleton方法里要进行这样的判断?
2)一般来说我们使用spring时候,都是单线程的。那么按照这个代码,创建之前添加进去,添加之后删除。那么岂不是永远不会走到这个if条件里?这些问题先记着,等分析依赖注入时候再回过头来解决。

总结

到了这里,还是有很多不知道有什么用的缓存。这些缓存会在研究依赖注入以及循环引用时候继续分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538057.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chkconfig: 2345 20 80

#chkconfig: 2345 20 80 2345表示系统运行级别是2&#xff0c;3&#xff0c;4或者5时都启动此服务&#xff0c;20&#xff0c;是启动的优先级&#xff0c;80是关闭的优先级&#xff0c;如果启动优先级配置的数太小时如0时&#xff0c;则有可能启动不成功&#xff0c;因为此时可…

android 按键上浮动画_android – 浮动动作按钮动画

从Zielony的回答中,我确切地说到了我想要的地方.下面是正确应用效果的代码.scale_fab_in.xmlandroid:duration"500"android:fromXScale"0"android:fromYScale"0"android:pivotX"50%"android:pivotY"50%"android:toXScale&qu…

性能测试调优篇---未完待续

性能测试调优一&#xff1a;1.首先&#xff0c;看下选测交易的整个走向纯系统内部交易&#xff1a;选测交易如果是系统内的交易&#xff0c;每一步请求都和系统交互几次&#xff0c;访问了几个数据库&#xff0c;访问了数据库的那几张表&#xff1f;&#xff1f;该交易走了那几…

mysql连接idea详细教程_idea配置连接数据库的超详细步骤

学习时&#xff0c;使用IDEA的时候&#xff0c;需要连接Database&#xff0c;连接时遇到了一些小问题&#xff0c;下面记录一下操作流程以及遇到的问题的解决方法。一、 连接操作简介&#xff1a;介绍如何创建连接&#xff0c;具体连接某个数据库的操作流程。1.1 创建连接打开i…

redis单节点安装

1、下载 redis &#xff1a;https://redis.io/ redis 提供的是 源码包&#xff0c;需要编译。 2、Linux下安装gcc 和 tcl tcl介绍 命令&#xff1a;yum install gcc tcl 3、将redis的源码包&#xff0c;放到 /usr/local/src 下 tar -zxvf redis-4.0.6.tar.gz 4、安装redi…

Shell编程—企业生产案例

Linux系统Shell编程—企业生产案例&#xff08;一&#xff09; 企业数据库可以说是重点保护对象啊&#xff0c;没有之一&#xff0c;数据在当今企业里就是生命线&#xff0c;因此今天就来说一说&#xff0c;如何通过shell脚本来检查或监控MYSQL数据库服务是否正常&#xff1f;&…

ManicTime软件破解

这款软件用来记录电脑上程序的运行时间。方便天天用电脑的查看&#xff1a;今天我的时间都去哪儿了&#xff1f; 专业版不免费&#xff0c;而且需要 67 美元。 免费版和专业版的区别 破解补丁和官方软件下载&#xff08;截止博文发布&#xff0c;官方最新版本 版本&#xff1…

mysql根据ID的顺序查找_求救:mysql 如何根据给定的 ID顺序查找结果?

各位大神&#xff0c;现在我遇到了一个难题需要你们的帮助。有下面两个表post表&#xff1a;文章表。record表:记录表&#xff0c;用于记录用户阅读顺序。record表 根据用户的阅读文章顺序用一个字段 postid 记录 post 表的主键ID&#xff0c;既 record.postid 的外键为 post.i…

DIY—USB学习板设计以及驱动开发

暑假在Intel OTC做访问学者时&#xff0c;看到公司有两个小巧的USB设备-温度计和LED音乐播放器&#xff0c;用于交大学生的Linux Kernel教学中。但看似简单的这些设备&#xff0c;还是从国外购买而得。因此&#xff0c;从intel回来之后&#xff0c;我就告诉学生能否设计一种USB…

ps -ef |grep

[rootzengmg 6379]# ps -ef | grep redisroot 1978 1 0 09:35 ? 00:00:16 /usr/local/bin/redis-server 127.0.0.1:6379 root 116656 2708 0 15:56 pts/1 00:00:00 grep redis 字段含义如下&#xff1a; UID PID PPID CSTIME…

python入坑指南_Rust入坑指南:万物初始

有没有同学记得我们一起挖了多少个坑&#xff1f;嗯…其实我自己也不记得了&#xff0c;今天我们再来挖一个特殊的坑&#xff0c;这个坑可以说是挖到根源了——元编程。元编程是编程领域的一个重要概念&#xff0c;它允许程序将代码作为数据&#xff0c;在运行时对代码进行修改…

python和noip的区别_【noi与noip的区别】

什么是NOINOI&#xff1a;全国青少年信息学奥林匹克(NOI)是国内包括港澳在内的省级代表队高水平的大赛&#xff0c;自1984年至今&#xff0c;在国内包括香港、澳门组织竞赛活动。每年经各省选拔产生5名选手(其中一名是女选手)&#xff0c;由中国计算机学会在计算机普及较好的城…

gradle和maven区别

原文连接&#xff1a;http://blog.csdn.net/jueane/article/details/50383431 --------------------------------------------- Gradle和Maven都是项目自动构建工具&#xff0c;编译源代码只是整个过程的一个方面&#xff0c;更重要的是&#xff0c;你要把你的软件发布到生产…

iOS开发提问题

1、打造最受企业欢迎的iOS开发者&#xff1a; 一直都存在的问题&#xff0c;什么样的员工最受企业欢迎&#xff1f;一直也有人在努力提升自己&#xff0c;成为受企业欢迎的员工然而&#xff0c;我们应该往方向去提升自己呢&#xff1f;88家知名企业今年来iOS面试题合集&#xf…

maven引用公共包_使用github作为maven仓库存放发布自己的jar包依赖 实现多个项目公共部分代码的集中,避免团队中多个项目之间代码的复制粘贴...

使用github作为maven仓库存放发布自己的jar包依赖 实现多个项目公共部分代码的集中&#xff0c;避免团队中多个项目之间代码的复制粘贴。1、首先在本地maven位置的配置文件setting.xml(没有该文件就新建这个文件)中&#xff0c;添加配置maven仓库的地址。我用的是我的GitHub仓库…

Gradle笔记——Gradle的简介与安装

原文连接&#xff1a;http://blog.csdn.net/maosidiaoxian/article/details/40109337 gradle专栏 ----------------------------------------- Gradle 安装 1&#xff0c;安装JDK&#xff0c;并配置JAVA_HOME环境变量。因为Gradle是用Groovy编写的&#xff0c;而Groovy基于JA…

WPF之鼠标滑动切换图片

原文:WPF之鼠标滑动切换图片在网上找了一会儿也没找到我想要的效果&#xff0c;还是自己动手&#xff0c;丰衣足食吧。 需求&#xff1a;当前面板中只显示一张图片&#xff0c;图片栏的下部有用来显示当前图片处于图片队列中的位置的圆球&#xff0c;并且点击下部栏内的圆球可以…

CPU的核心数、线程数的关系和区别

原文地址&#xff1a;http://blog.csdn.net/yu132563/article/details/45222935 ------------------------------------- 我们在选购电脑的时候&#xff0c;CPU是一个需要考虑到核心因素&#xff0c;因为它决定了电脑的性能等级。CPU从早期的单核&#xff0c;发展到现在的双核…

mysql in 子查询优化_mysql in 子查询 容易优化

mysql in 子查询 简单优化 大数量下&#xff0c;不要使用 in 嵌套子查询&#xff0c;性能很差&#xff0c;很容易卡死。 ? 简单调整方式如下&#xff1a; select uid,nick_name from uc_users where uid in(select fid from uc_follow where uid#uid#) ? 可拆解成&#xff1a…

谷歌浏览器插件入门示例

2019独角兽企业重金招聘Python工程师标准>>> 实现&#xff1a;任何网址实现图片下载和获取当前域名的cookies的json字符串。 图片下载是给小白用的&#xff0c;可以选中批量下载&#xff0c;获取cookies 是为了方便程序员调试用。 获取cookies: git地址&#xff1a;…