Spring源码学习笔记9——构造器注入及其循环依赖

一丶前言

前面我们分析了spring基于字段的和基于set方法注入的原理,但是没有分析第二常用的注入方式(构造器注入)(第一常用字段注入),并且在循环依赖问题上构造器注入常被说spring无法解决构造器注入的循环依赖,下面我们来分析构造器注入和其循环依赖的源码

二丶构造器依赖注入

在spring初始化每一个非抽象,单例,非懒加载的bean的时候,会调用createBeanInstance方法去创建bean的实例,在使用默认的策略——无参构造or CGLIB生成子类对象的方式之前,先会使用所有的SmartInstantiationAwareBeanPostProcessor 来判断是否有用户指定的后置处理器

1.循环调用所有的SmartInstantiationAwareBeanPostProcessor实现类来推断该使用哪个构造器

这里重点是使用到了AutowiredAnnotationBeanPostProcessor来推断

2.AutowiredAnnotationBeanPostProcessor 推断构造器的逻辑

首先AutowiredAnnotationBeanPostProcessor 有一个缓存key是bean类型,value是之前推断的所有构造器数组。自然是一波双if+synchronized方式来读缓存中内容,缓存没有命中再进行推断

遍历每一个构造器(这里省去了spring对Kotlin语言支持的部分)
1.获取当前构造器上面的@Autowired 和 @Value 注解
2.如果注解信息为空,且当类是一个被CGLIB代理后的类,
会获取父类构造器上面的注解(要求父类构造器和当前遍历到的构造器参数类型顺序相同)
3.如果注解信息不为空,会检查 required 属性的信息
(spring还支持ejb等的注解,所有这里检查require的信息)像@Autowired 和 @Value这种不包含required属性的注解会默认是required为true,
并且记录当前构造器为候选者,也就是说有注解的才算在候选者
4.如果存在多个required=true的构造器抛出异常,
否则使用遍历记录当前required=true的构造器
5.如果候选者不为空,required=true的构造器为空
(一般这种情况是标注了EJB的注解指定required为false)spring会把无参构造加入到候选者中
6.如果原来类只定义了一个有参构造,那么使用这个有参构造 如果不考虑EJB中的依赖注入注解
那么就是如果构造器有@Autowired or @Value那么默认使用它
如果定义了一个有参构造那么使用这个有参构造 其他情况一律返回null(后续spring可能使用无参构造or CGLIB生成子类的方式)

3.使用构造器进行依赖注入的逻辑

推断出使用哪个构造器之后,spring调用autowireConstructor方法进行构造器注入,具体逻辑委托给ConstructorResolver的autowireConstructor方法,最终解析依赖注入参数的在createArgumentArray方法中进行,一般是调用resolveAutowiredArgument方法

最终还是殊途同归的调用到了beanFactory的resolveDependency方法

4.实例化对象

这一步还是调用的instantiate方法

三丶为什么构造器的循环依赖spring无法解决

1.构造方法注入无法解决循环依赖的情况及其原因

如果是这种循环依赖的情况spring是无法解决循环依赖的,下面是这种循环依赖出现时候的代码流程

问题出现在beforeSingletonCreation方法中

在spring创建bean的之前使用了set维护正在创建bean的名称,B需要A,再次创建A的时候就发现set中原本存在A,这时候就是无法解决循环依赖的情况,会抛出异常

同理这种情况也是不可以解决的

2.构造方法注入可以解决循环依赖的情况及其原因

这种情况下spring又是可以解决循环依赖的



原因是A是可以成功使用无参构造实例化的,所以B需要A的时候可以在三级缓存拿到A的ObjectFactory,调用后得到A,而不是再次创建A

我们可以得到结论

如果加载顺序是A然后B,那么A只能是字段注入or方法注入,不能是构造器注入
B无所谓那种注入方式

Spring源码学习笔记9——构造器注入及其循环依赖的更多相关文章

  1. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  2. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  3. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  4. spring源码学习笔记之容器的基本实现(一)

    前言 最近学习了<<Spring源码深度解析>>受益匪浅,本博客是对学习内容的一个总结.分享,方便日后自己复习或与一同学习的小伙伴一起探讨之用. 建议与源码配合使用,效果更嘉, ...

  5. Spring源码学习笔记之bean标签属性介绍及作用

    传统的Spring项目, xml 配置bean在代码中是经常遇到, 那么在配置bean的时候,这些属性的作用是什么呢? 虽然说现在boot项目兴起,基于xml配置的少了很多, 但是如果能够了解这些标签 ...

  6. Spring源码学习笔记之基于ClassPathXmlApplicationContext进行bean标签解析

    bean 标签在spring的配置文件中, 是非常重要的一个标签, 即便现在boot项目比较流行, 但是还是有必要理解bean标签的解析流程,有助于我们进行 基于注解配置, 也知道各个标签的作用,以及 ...

  7. 【spring源码系列】之【Bean的循环依赖】

    希望之光永远向着目标清晰的人敞开. 1. 循环依赖概述 循环依赖通俗讲就是循环引用,指两个或两个以上对象的bean相互引用对方,A依赖于B,B依赖于A,最终形成一个闭环. Spring循环依赖的场景有 ...

  8. Spring源码学习笔记1

    1.Spring中最核心的两个类 1)DefaultListableBeanFactory XmlBeanFactory继承自DefaultListableBeanFactory,DefaultLis ...

  9. Spring源码学习笔记2

    1.默认标签的解析 对四种不同标签的解析 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate dele ...

随机推荐

  1. zabbix脚本获取web status code,异常告警

    python代码,需要安装requests库 1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 import requests,os,sys 4 url ...

  2. Java注解Annotaton

    1.三种基本的Annotaton @Override : 限定某个方法,是重写父类方法 , 该注解只能用于方法 @Deprecated : 用于表示某个程序元素 ( 类 , 方法等 ) 已过时 @Su ...

  3. 好客租房20-react组件介绍

    1react组件介绍 组件是react中的一等公民 组件表示页面中的部分功能 组合多个组件实现完整的页面功能 特点 可复用性 独立 可组合

  4. 有趣的BUG之Stack Overflow

    今天遇到一个很有意思的bug,当程序开发完成后打包到服务器运行,总是会出现栈溢出异常,经过排查发现,问题出现在一个接口上,但这个接口逻辑并不复杂,除了几局逻辑代码外和打印语句之外也没有其他的了,但是只 ...

  5. Servlet的本质

    简介:Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层. 功能:使 ...

  6. python实现对简单的运算型验证码的识别【不使用OpenCV】

    最近在写我们学校的教务系统的手机版,在前端用户执行绑定操作后,服务器将执行登录,但在登录过程中,教务系统中有个运算型的验证码,大致是这个样子的: 下面我们开始实现这个验证码的识别. 1.图片读取 从网 ...

  7. .NET 6.0.6 和 .NET Core 3.1.26、Visual Studio 2022 17.2 和 17.3 Preview 2 和 .NET 7.0 Preview 5 同时发布

    Microsoft 昨天发布了适用于 .NET 6.0.6 和 .NET Core 3.1.26.NuGet.Visual Studio 2019 和 Visual Studio 2022 17.2 ...

  8. bitmap技术解析:redis与roaringBitmap

    bitmap的表象意义是,使用一个01标识位来表示是否的状态,可以达到节省空间和高效判定的效果.在我们的实际工作中,也有着许多的应用场景,相信了解bitmap定会给你带来一些额外的收获. 1. bit ...

  9. 最简单的离散概率分布,伯努利分布 《考研概率论学习之我见》 -by zobol

    上文讲了离散型随机变量的分布,我们从最简单的离散型分布伯努利分布讲起,伯努利分布很简单,但是在现实生活中使用的很频繁.很多从事体力工作的人,在生活中也是经常自觉地"发现"伯努利分布 ...

  10. 关于一次Web线下面试的思考

    前言: 今天面试一家Web前端的公司,由于跟初筛的面试官关系挺好,按理来说我在第一次线上面试就应该被淘汰了(呜呜呜),接下来是线下面试,不出意外的话,我凉了.但是这些天的面试经验并非全无收获.我的线下 ...