Spring 循环依赖

2023-11-13

Spring 循环依赖

1. 什么是循环依赖?

抛开 Spring 框架不说,先来了解循环依赖的本质

image-20211006181701817

从上图总可以看出依赖关系

  • A 依赖 B
  • B 依赖 C
  • C 依赖 A

这种依赖的关系就造成了循环依赖的发生

让我们从代码的角度来看看循环依赖是如何产生以及如何被解决的

定义两个类 A 和 B

public class A {
    private B b;
}

public class B {
    private A a;
}

模仿Spring:假装 A 和 B 是被 @Component 修饰,并且类中的字段假装是 @Autowired 修饰的,处理完放到 Map 中

	 /**
     * 放置创建好的bean Map
     */
    private static Map<String, Object> cacheMap = new HashMap<>(2);

    public static void main(String[] args) {
        // 假装扫描出来的对象
        Class[] classes = {A.class, B.class};
        // 假装项目初始化实例化所有bean
        for (Class aClass : classes) {
            getBean(aClass);
        }
        // check
        System.out.println(getBean(B.class).getA() == getBean(A.class));
        System.out.println(getBean(A.class).getB() == getBean(B.class));
    }

    @SneakyThrows
    private static <T> T getBean(Class<T> beanClass) {
        // 本文用类名小写 简单代替bean的命名规则
        String beanName = beanClass.getSimpleName().toLowerCase();
        // 如果已经是一个bean,则直接返回
        if (cacheMap.containsKey(beanName)) {
            return (T) cacheMap.get(beanName);
        }
        // 将对象本身实例化
        Object object = beanClass.getDeclaredConstructor().newInstance();
        // 放入缓存
        cacheMap.put(beanName, object);
        // 把所有字段当成需要注入的bean,创建并注入到当前bean中
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            // 获取需要注入字段的class
            Class<?> fieldClass = field.getType();
            String fieldBeanName = fieldClass.getSimpleName().toLowerCase();
            // 如果需要注入的bean,已经在缓存Map中,那么把缓存Map中的值注入到该field即可
            // 如果缓存没有 继续创建
            field.set(object, cacheMap.containsKey(fieldBeanName)
                    ? cacheMap.get(fieldBeanName) : getBean(fieldClass));
        }
        // 属性填充完成,返回
        return (T) object;
    }

这段代码的效果,其实就是处理了循环依赖,并且处理完成后,cacheMap 中放的就是完整的 Bean
640

参考:https://mp.weixin.qq.com/s?__biz=MzAwNDA2OTM1Ng==&mid=2453143515&idx=1&sn=c15f40f4f45bf155fe7eddb7dc2c9080&scene=21

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

Spring 循环依赖 的相关文章

随机推荐

  • Tomcat配置context.xml问题

    关于Tomcat的配置文件问题 请参考Apache Tomcat官网Document菜单 根据版本号选择恰当的Reference 我使用的环境 netbeans 内嵌 Tomcat 8 0 1
  • 彻底删除VMware虚拟机

    您是否和我一样被VMware气到了呢 您是否再也不想理VMware了呢 您是否不想再在自己电脑上看到VMware这几个英文字母了呢 来吧 跟着我的步骤 一起和VMware说拜拜吧 一 在卸载VMware虚拟机之前 要先把与VMware相关的
  • 工业上的数控机床所属计算机应用的什么领域,以下哪一项不是企业初步战略方案包括的内容?()。...

    摘要 弹簧振子的振幅增加一倍 下业初则 步战工业机器人最重要的核心能力 社会学是指一门科学 略方即它以解释的方式来理解社会行动 略方据此 通过社会行为的过程及其结果 对社会行为作出因果解释 因此 社会学的研究对象是 研究的方法是 弹簧振子的
  • 西门子S7 模拟器使用教程

    一 S7协议概述 S7协议是西门子S7系列PLC通信的核心协议 它是一种位于传输层之上的通信协议 其物理层 数据链路层可以是MPI总线 PROFIBUS总线或者工业以太网 S7以太网协议本身也是TCP IP协议簇的一员 S7协议在OSI中的
  • PCB中过孔和通孔焊盘的区别

    在PCB设计中 过孔VIA和焊盘PAD都可以实现相似的功能 它们都能插入元件管脚 特别是对于直插 DIP 封装的的器件来说 几乎是一样的 但是 在PCB制造中 它们的处理方法是不一样的 1 VIA的孔在设计中表明多少 钻孔就是多少 然后还要
  • 接口继承_1

    摘自Jeffrey的CLR via CSharp 接口方法默认是virtual and sealed 意思是接口方法默认是没有继承的 这一点在你需要多态时需要注意 Base b new Base Derived d new Derived
  • 修改Windows Server 2012远程桌面连接端口并连接

    目录 文章目录 目录 一 修改注册表 二 添加防火墙放行端口 三 控制面板设置允许被远程连接 四 重启远程桌面服务 五 进行远程连接 一 修改注册表 步骤1 打开注册表 方法一 win键 R调出命令运行输入框 输入 regedit exe
  • 网络安全-常见面试题(Web、渗透测试、密码学、Linux等)

    目录 WEB安全 OWASP Top 10 2017 Injection 注入攻击 Broken Authentication 失效的身份认证 Sensitive Data Exposure 敏感数据泄露 XXE XML 外部实体 Brok
  • C#开发-----百变方块游戏

    转载请标明是引用于 http blog csdn net chenyujing1234 例子代码 http www rayfile com zh cn files b6ed0bc0 8e9e 11e1 8178 0015c55db73d n
  • Web前端开发精品课HTML CSS JavaScript基础教程HTML部分知识点总结

    内容来自莫振杰Web前端开发精品课HTML CSS JavaScript基础教程章节总结 第1章 HTML简介 1 前端技术简介 1 从Web1 0到Web2 0 网页制作已经变成前端开发了 对于前端开发来说 你要学的并不是什么 网页三剑客
  • 宿主机无法ping通docker容器IP解决

    背景 安装docker后 发现启动容器的端口8082 映射到宿主机的端口80访问主机没有反应 此时进入容器查看日志 发现并没有请求打进来 现象 正在连接 localhost localhost 1 80 已连接 已发出 HTTP 请求 正在
  • python3 Flask 简单入门

    flask是python里面最轻便的框架 这里演示了访问主页 登陆成功 登陆失败的页面显示 在编写URL处理函数时 除了配置URL外 从HTTP请求拿到用户数据也是非常重要的 Web框架都提供了自己的API来实现这些功能 Flask通过re
  • android游戏开发基础

    学习android已经差不多接近一年了 以前一直做的android应用 现在准备搞android游戏开发 觉得以前都没能把做应用的经验总结下来 现在决定要把游戏这块的记录下来 声明我也是初学者 首先得有一定的数学与物理基础 其次得具有一定的
  • ICLR 2022 超越Focal Loss PolyLoss用1行代码+1个超参完成超车

    pytorch版 有两种 交叉熵版和Poly1FocalLossloss GitHub abhuse polyloss pytorch Polyloss Pytorch Implementation 分类版 PolyLoss polylos
  • java-jdbc-db2

    0 得到结果集的一种方式 查询得到结果集的另一种方式 Statement stmt con createStatement String sql select value from restart ResultSet rs stmt exe
  • 交换机(三层)转发原理

    1 三层交换机转发原理 如图所示 假如主机A想访问主机B 首先主机A会将自己的IP地址和子网掩码做与操作 得出网路地址 如 Host A的IP地址100 1 1 2与自身掩码255 255 255 0做与操作后 得到的网络号是100 1 1
  • window.parent.document解决方案【原生js或jQuery 实现父窗口的问题】

    做WEB前端开发的过程中 经常会有这样的需求 用户点击 编辑 按钮 弹出一个对话框 在里边修改相应的值 然后把修改后的值显示在原页面 最后点击保存 用window parent document getElementById setAttr
  • application.yml、mybatis-generatorConfiguration配置

    pom xml配置
  • 三. Netty 进阶

    Netty学习之路 一 NIO基础 二 Netty 入门 三 Netty 进阶 四 Netty 优化与源码 学完netty手写了一个rpc项目 链接 https gitee com springchuntian1 netty rpc 笔记源
  • Spring 循环依赖

    Spring 循环依赖 1 什么是循环依赖 抛开 Spring 框架不说 先来了解循环依赖的本质 从上图总可以看出依赖关系 A 依赖 B B 依赖 C C 依赖 A 这种依赖的关系就造成了循环依赖的发生 让我们从代码的角度来看看循环依赖是如