AI 助理
备案 控制台
开发者社区 开发与运维 文章 正文

Spring循环依赖原理和Bean创建过程

简介: Spring循环依赖原理和Bean创建过程

Spring 循环依赖

1.什么是循环依赖

循环依赖就是指Spring在创建Bean的过程中,一个Bean的属性依赖另一个Bean,而被依赖的Bean又依赖于当前Bean,如下图所示:

代码如下:

StudentService.java

public class StudentService {
    private TeacherService teacherService;
    //因为要依赖注入,在这里我们先使用setter注入
    public void setTeacherService(TeacherService teacherService) {
        this.teacherService = teacherService;
    }
    static {
        System.out.println("创建StudentServiceBean...");
    }
}

TeacherService.java

public class TeacherService {
    private StudentService studentService;
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }
    static {
        System.out.println("创建teacherServiceBean...");
    }
}

测试:

@Test
public void beanTest01() {
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    {
        RootBeanDefinition stu = new RootBeanDefinition(StudentService.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("teacherService", new RuntimeBeanReference("teacherService"));
        stu.setPropertyValues(new MutablePropertyValues()
                .addPropertyValues(map));
        factory.registerBeanDefinition("studentService", stu);
    }
    {
        RootBeanDefinition tea = new RootBeanDefinition(TeacherService.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("studentService", new RuntimeBeanReference("studentService"));
        tea.setPropertyValues(new MutablePropertyValues()
                .addPropertyValues(map));
        factory.registerBeanDefinition("teacherService", tea);
    }
    StudentService bean = factory.getBean(StudentService.class);
    System.out.println(bean);
}

debug一下看看效果:

显然,Spring创建的都是单例的Bean,循环依赖的完成也是由Spring自动进行的,下面我们从创建bean开始来了解Spring是如何解决循环依赖的。

2.Spring创建对象的过程

2.1 大致过程

大致过程无非就是这样:

2.2 实际创建过程

详细过程就需要涉及到工厂模式、抽象工厂、单例池…

主要类的依赖图(全部为继承关系):

  • 首先调用公开方法 DefaultListableBeanFactory.getBean(Class cls) 来获取 Bean 对象,通过一系列操作转化 class 对象为 beanName。
  • 得到 beanName 之后,调用 AbstractBeanFactory.getBean(String name, Class cls) , 在这个方法中又会调用受保护的 AbstractBeanFactory.doGetBean 方法
  • doGetBean 方法中,又会调用 DefaultSingletonBeanFactory.getSingleton(String beanName, ObjectFactory factory)
  • getSingleton 方法中,首先在单例池 DefaultSingletonBeanFactory.singletonObjects 查找是否已经存在 beanName 对应的单例对象。如果找不到,那会调用函数式接口 ObjectFactory 来创建一个对象,而这个对象工厂调用的函数是一个受保护的抽象方法 AbstractBeanFactory.crateBean(String beanName, RootBeanDefinition def, Object[] args)
  • AbstractAutowireCapableBeanFactory 实现了超类的 createBean 方法, 并在 createBean 方法中调用了受保护的方法 AbstractAutowireCapableBeanFactory.doCreateBean
  • doCreateBean方法中,还会调用 AbstractAutowireCapableBeanFactory.populateBean 来填充属性。
  • populateBean 填充属性时,还可能遇上没有创建过的对象,因此还可能递归调用 AbstractBeanFactory.getBean(String beanName)

AbstractAutowireCapableBeanFactory 负责了实例化 Bean,填充属性,后置处理的任务,DefaultSingletonBeanRegistry 负责了单例池的维护工作

3.Spring是如何解决循环依赖的

Spring 就是靠获取未完成的Bean对象来填充属性,解决循环依赖的。(这里使用到了三级缓存)

基本过程:

(1)通过getSingleton()时添加,Bean创建状态

(2)实例化Bean之后添加ObjectFactory至工厂池

(3)获取创建状态的Bean时,会先通过ObjectFactory获取Bean,然后添加到半成品池earlySingletonObjects

(4)对象完成创建后会添加到单例池

为什么不直接把对象放入 earlySingletonObjects,而是先放入 singletonFactories 中?

创建对象是需要消耗性能的,假如创建没有循环依赖的对象,是不需要创建未完成的Bean对象的,所以不是直接创建未完成对象放入未完成单例集 earlySingletonObjects,而是把未完成单例工厂放入 singletonFactories

比如以下这段代码,在运行时就不会调用 getSingleton 中的 ObjectFactory.getObject() 方法来创建未完成 Bean 对象。

4.什么情况下不能解决循环依赖

在Bean是多例的状态下不能解决循环依赖(因为按理来说要创建无数个Bean)

试一下:

@Test
public void beanTest01() {
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    {
        RootBeanDefinition stu = new RootBeanDefinition(StudentService.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("teacherService", new RuntimeBeanReference("teacherService"));
        stu.setPropertyValues(new MutablePropertyValues()
                .addPropertyValues(map));
        stu.setScope("prototype");  //将StudentService设置为多例模式
        factory.registerBeanDefinition("studentService", stu);
    }
    {
        RootBeanDefinition tea = new RootBeanDefinition(TeacherService.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("studentService", new RuntimeBeanReference("studentService"));
        tea.setPropertyValues(new MutablePropertyValues()
                .addPropertyValues(map));
        factory.registerBeanDefinition("teacherService", tea);
    }
    StudentService bean = factory.getBean(StudentService.class);
    System.out.println(bean);
}

报错:


海风极客
目录
相关文章
石小浪♪
|
9天前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
石小浪♪
44 9
Spring从入门到入土(bean的一些子标签及注解的使用)
dlwlrma-晴子
|
6天前
|
Java Spring 容器
Spring底层原理大致脉络
Spring底层原理大致脉络
dlwlrma-晴子
19 4
猿java
|
9天前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
猿java
36 1
喜欢猪猪
|
17天前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
喜欢猪猪
63 9
Codelinghu
|
11天前
|
Java Spring
获取spring工厂中bean对象的两种方式
获取spring工厂中bean对象的两种方式
Codelinghu
12 1
猿java
|
12天前
|
缓存 Java Spring
源码解读:Spring如何解决构造器注入的循环依赖?
本文详细探讨了Spring框架中的循环依赖问题,包括构造器注入和字段注入两种情况,并重点分析了构造器注入循环依赖的解决方案。文章通过具体示例展示了循环依赖的错误信息及常见场景,提出了三种解决方法:重构代码、使用字段依赖注入以及使用`@Lazy`注解。其中,`@Lazy`注解通过延迟初始化和动态代理机制有效解决了循环依赖问题。作者建议优先使用`@Lazy`注解,并提供了详细的源码解析和调试截图,帮助读者深入理解其实现机制。
猿java
17 1
猿java
|
12天前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细介绍了Spring框架中的核心概念——Spring Bean的生命周期,包括实例化、属性赋值、接口回调、初始化、使用及销毁等10个阶段,并深入剖析了相关源码,如`BeanFactory`、`DefaultListableBeanFactory`和`BeanPostProcessor`等关键类与接口。通过理解这些核心组件,读者可以更好地掌握Spring Bean的管理和控制机制。
猿java
45 1
喜欢猪猪
|
23天前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
喜欢猪猪
31 4
猿java
|
9天前
|
XML 前端开发 Java
拼多多1面:聊聊Spring MVC的工作原理!
本文详细剖析了Spring MVC的工作原理,涵盖其架构、工作流程及核心组件。Spring MVC采用MVC设计模式,通过DispatcherServlet、HandlerMapping、Controller和ViewResolver等组件高效处理Web请求。文章还探讨了DispatcherServlet的初始化和请求处理流程,以及HandlerMapping和Controller的角色。通过理解这些核心概念,开发者能更好地构建可维护、可扩展的Web应用。适合面试准备和技术深挖
猿java
30 0
何雨晨
|
10天前
|
负载均衡 Java API
Spring Cloud原理详解
Spring Cloud原理详解
何雨晨
41 0

热门文章

最新文章

  • 1
    Spring Boot 中文乱码问题解决方案汇总
  • 2
    Spring-boot+Dubbo应用启停源码分析
  • 3
    深入解析@SpringBootApplication注解:简化Spring Boot应用的配置
  • 4
    深入理解Spring--动手实现一个简单的SpringIOC容器
  • 5
    基于Spring3 MVC实现基于HTML form表单文件上传
  • 6
    猿创征文|Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time.
  • 7
    【Spring实战】—— 15 Spring JDBC模板使用
  • 8
    Spring IOC 容器源码分析
  • 9
    第13章 SpringBoot集成模板引擎
  • 10
    Spring Assert主张 (参议院检测工具的方法-主张)
  • 1
    Spring Boot中的@Lazy注解:概念及实战应用
    136
  • 2
    docker部署postgresql数据库和整合springboot连接数据源
    143
  • 3
    spring kafka的问题集锦
    142
  • 4
    【spring】如何解决循环依赖
    202
  • 5
    【springboot】logback配置
    72
  • 6
    Python 爬虫:Spring Boot 反爬虫的成功案例
    638
  • 7
    JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
    543
  • 8
    Spring Boot版本管理
    46
  • 9
    Spring的@Retryable实现方法重试
    65
  • 10
    Spring Boot可以同时处理多少请求?
    111
  • 相关课程

    更多
  • 精通Spring Cloud Alibaba
  • 微服务框架 Spring Cloud 快速入门
  • Java Web开发系列课程 - Spring框架入门
  • Spring Boot 2.5.x开发实战
  • Spring Cloud微服务架构设计与开发实战
  • 相关电子书

    更多
  • 云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧
  • 微服务架构模式与原理Spring Cloud开发实战
  • 阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库
  • 相关实验场景

    更多
  • 从零搭建Spring Boot的Hello World
  • 下一篇
    AI助理直击要害,从繁复中提炼精华——使用CDN加速访问OSS存储的图片

    玻璃钢生产厂家玻璃钢花盆如何制作衢州卡通玻璃钢雕塑工艺四川特色玻璃钢雕塑市场玻璃钢北极熊雕塑作品绍兴玻璃钢雕塑厂招聘信息德州玻璃钢人物镜面不锈钢雕塑上海商场美陈匠心品质3月商场美陈布置四川周年庆典商场美陈有哪些昆明玻璃钢游乐场门头雕塑耐用性好玻璃钢雕塑郑州铸造校园玻璃钢雕塑小品甘肃主题公园玻璃钢雕塑厂家南平企业玻璃钢雕塑许昌玻璃钢不锈钢树叶雕塑周口佛像玻璃钢卡通雕塑咸阳广场玻璃钢雕塑定做促销玻璃钢迎宾雕塑大理市玻璃钢雕塑价格百色玻璃钢雕塑小品商场美陈投标标书做玻璃钢雕塑用什么漆合肥玻璃钢花盆批发价格表朝阳玻璃钢花盆生产厂家玻璃钢雕塑模具的制作流程永城玻璃钢雕塑厂家云南特色玻璃钢雕塑生产厂家东营玻璃钢雕塑商家美陈玻璃钢卡通雕塑销售电话郑州泡沫玻璃钢景观雕塑生产厂家香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

    玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化