【spring源码探索】一分钟搞懂RefreshScope的作用及实现原理

2023-10-26

前文

下述文章完全为个人阅读源码的随笔记录,如有错误,欢迎大家指出。

过程

过程很坎坷,而且大家应该都不想看了吧,简而言之就是先写个测试DEMO,然后各种DEBUG。

结论

这次先直接上结论,然后再通过测试DEMO给出验证,最后再去跟代码。
RefreshScope的作用介于Singleton和Prototype之间,你说他是单例啊,他在某些条件下是单例,你说他是多例把,他确实在某些条件下也是多例。
这个条件就在于Refresh。

加了RefreshScope注解的bean,每次容器刷新后,都会重新生成一个对象。

顺便记录一下底层的实现把:

在IOC容器里面,有一个map类型的scopes的缓存,他会根据scope名称不同,分为request、session、refresh、application(至于为啥没有单例和多例,因为单例的缓存已经放在singleObjects里面了,多例就更不用说,压根就不需要缓存)。

咱们这次的关注点是refresh,他map里面取出来的对象就是RefreshScope,RefreshScope的父类GenericScope有一个叫BeanLifecycleWrapperCache,这玩意是缓存的包装对象了,里面的ScopeCache其实也就是一个KEY为beanName,Value是bean的Map缓存,只是这个缓存跟单例池唯一的区别就是他对外提供了一个清空方法(其实单例池咱们也可以给他时改造成这样)

只要调用RefreshScope的refreshAll()方法,就会清空这个缓存,下次再取bean的时候,从缓存里面取不到自然就会重新走getBean()方法重新生成再放进这个缓存里面了。

最后附一个可以直接开DEBUG的DEMO,对源码感兴趣的同学可以兄弟可以直接拿去开搞,请原谅我反射直接做的搬砖工。

	public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext run = SpringApplication.run(Consumer03.class, args);
        Object eurekaClient = run.getBean("scopedTarget.eurekaClient");
        Object eurekaClient1 = run.getBean("scopedTarget.eurekaClient");

        ConfigurableListableBeanFactory beanFactory = run.getBeanFactory();
        Map<String, Scope> scopes = (Map<String, Scope>) getFieldValueByObject(beanFactory, "scopes");
        RefreshScope refreshScope = (RefreshScope) scopes.get("refresh");
        refreshScope.refreshAll();

        Object eurekaClient2 = run.getBean("scopedTarget.eurekaClient");

        System.out.println(eurekaClient1 == eurekaClient);
        System.out.println(eurekaClient1 == eurekaClient2);
    }

    public static Object getFieldValueByObject(Object object, String targetFieldName) throws Exception {

        // 获取该对象的Class
        Class sonClass = object.getClass();
        Class<?> objClass = sonClass.getSuperclass().getSuperclass();

        // 初始化返回值
        Object result = null;

        // 获取所有的属性数组
        Field[] fields = objClass.getDeclaredFields();
        for (Field field : fields) {
            // 属性名称
            String currentFieldName = "";

            try {
                currentFieldName = field.getName();
                System.out.println("currentFieldName:"+currentFieldName);
                if (currentFieldName.equals(targetFieldName)) {
                    field.setAccessible(true);
                    result = field.get(object);

                    return result; // 通过反射拿到该属性在此对象中的值(也可能是个对象)
                }

            } catch (SecurityException e) {
                // 安全性异常
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // 非法参数
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // 无访问权限
                e.printStackTrace();
            }
        }

        return result;
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【spring源码探索】一分钟搞懂RefreshScope的作用及实现原理 的相关文章

随机推荐

  • HTML_and_CSS

    HTML知识 1 html概念 html全称HyperText Markup Language 翻译为超文本标记语言 它不是一种编程语言 是一种描述性的标记语言 用于描述超文本内容的显示方式 比如字体 颜色 大小等 超文本 音频 视频 图片
  • MVC 和Spring MVC

    MVC 和Spring MVC 我们都知道常说的MVC指的是 Model View Controller 数据模型 视图 控制器 三层架构指的是 展现层 应用层 数据访问层 但是Spring MVC却不是指的上面的三层架构而是将展现层拆分成
  • 项目开发流程图

    项目开发流程图 抽空总结了下项目开发流程 大多数公司应该都沿用这个流程方式
  • Spire.Office for Java 8.9.5/Spire.Office 8.9.2 .NET

    Spire Office for NET is a combination of Enterprise Level Office NET API offered by E iceblue It includes Spire Doc Spir
  • VHDL棋类竞赛设计(一)

    设计要求 竞赛计时分两个阶段 每方50秒的规定用时和每方每步8秒的读秒 1 可分别显示甲乙双方规定用时阶段的已用时间和读秒阶段 8秒 的倒计时 2 设置两路输入模拟双方落子 在规定用时阶段 一路信号有效时会暂停本方计时并继续对方计时 而在读
  • 当easyui datagrid无数据时,显示特定值。如:没有数据

    lt html gt lt head gt lt meta charset UTF 8 gt lt title gt Basic DataGrid jQuery EasyUI Demo lt link rel stylesheet type
  • golang context使用reflect遍历获取所有的key和value

    golang中我们经常和context打交道 context实际上可以保存值 源码参见 usr local go src context context go context包中实际上有好几种私有的context类型 type emptyC
  • SpringCache笔记

    SpringCache 一 简介 1 缓存介绍 Spring 从 3 1 开始就引入了对 Cache 的支持 定义了 org springframework cache Cache 和 org springframework cache C
  • Python中float类型、float32类型和float64类型的表示精度,所需内存及其之间的转换

    1 表示精度和所需内存 float类型和float64类型是一样的 都需要64个bits 而float32需要32个bits 精度方面 float类型和float64类型在十进制中可以有16位 而float32类型在十进制中有8位 如下 g
  • 哔哩哔哩 API

    常用查看技巧 UP主所有视频 https www bilibili com medialist play 这里写uid from space 最新投稿的视频 https www bilibili com newlist html API 参
  • 完美解决Missing artifact com.oracle:ojdbc6:jar:11.2.0.4

    今天运行Tomcat项目时 在加载maven依赖的时候报了Missing artifact com oracle ojdbc6 jar 11 2 0 4的错 意思是说我缺少了com oracle ojdbc6 jar 11 2 0 4的依赖
  • 基于axios的二次封装

    1 axios的封装前言 axios是一个基于 promise 的 HTTP 库 目前 在vue react框架中也还是备受青睐 根据不同项目的业务 也有许多种不同的封装方法 但不同的应用场景 导致封装的代码风格不一 我这里想总结下封装的思
  • IDEA项目及字体样式和初始化等习惯配置

    前言 内容较多 按需检索 0 IDEA常用快捷键 1 主题设置 黑白 2 字体大小设置 3 全局编码 字符集改为utf 8 3 1 文件编码设置 3 2 新建项目字符集设置 3 3 单个文件编码设置 idea面板右下角 4 Maven配置
  • 如何设置环境变量

    首先强烈推荐一款免费的c 的IDE code block 免费的且自带了MinGW编译器 自己可以设置字体及大小 一般设置成12号比较合适 直接在界面上的Setting gt Editor 在右上角上有一个choose 然后就可以选择字体
  • 书城管理系统(前端)

    OK 兄弟们 测试上传图片的后端接口 测试分页条件查询后端接口 测试根据id查询后端接口 测试新增一本书的后端接口 测试修改一本书的后端接口 之前写好的后端接口 用postman测试一下 没有问题的话我们就试试开发前端 准备工作 用vue创
  • MYSQL 时间处理

    1 MySQL 获得当前时间戳函数 current timestamp current timestamp mysql gt select current timestamp current timestamp current timest
  • BERT使用过程中的碰到的那些报错

    BERT是谷歌2018年提出的语言模型 在十几个任务上达到了state of art 在这里本人在使用过程中总结了一下遇到的错误 BERT推荐在TPU上运行 但是资源有限在GPU上跑也行 不行也能在cpu上跑 ps就是有些慢 官方BERT的
  • RPA机器人成为金融银行业转型的重要推手

    当前 金融科技迅猛发展 金融业监管和合规要求不断提升 为了应对挑战 抓住机遇 银行业作为国民经济体系重要的组成部分和核心产业 早已开始探索科技赋能金融之路 当前银行业面临的难题 成熟的银行都会在其内部部署多个业务平台 管理系统 以实现业务流
  • arduino控制步进电机

    一 实物连接 二 代码实现 const int IN1 11 const int IN2 10 const int IN3 9 const int IN4 8 正转顺序 const char tab1 0x01 0x03 0x02 0x06
  • 【spring源码探索】一分钟搞懂RefreshScope的作用及实现原理

    前文 下述文章完全为个人阅读源码的随笔记录 如有错误 欢迎大家指出 过程 过程很坎坷 而且大家应该都不想看了吧 简而言之就是先写个测试DEMO 然后各种DEBUG 结论 这次先直接上结论 然后再通过测试DEMO给出验证 最后再去跟代码 Re