1,什么是spring-ioc
其实spring-ioc并不是一个概念,可以拆分为两个,一个是spring,一个是ioc,spring是一个java比较强大的开源框架,而spring-ioc只是这个框架核心功能一部分,这个搞java的都知道吧,那么ioc呢就是《控制反转》这里也不便多说,所以spring-ioc就是一个提供控制反转功能的框架。
2,什么是循环依赖
举个例子,a依赖于b,且b依赖于a,用xml文件表示就是
<bean name="a" class="com.chameleon.A"> <property name="b" ref="b"/> </bean> <bean name="b" class="com.chameleon.B"> <property name="a" ref="a"/> </bean>
可能大家会说,这没什么呢,注入进去就好了,但是如果研究过死锁的话可能就会发现一个问题,那就是在创建A 注入B的时候,接下来创建B注入A的话是不是会产生“死锁”呢?有可能的。
3,spring中依赖注入的种类
按照注入形式区分的话,spring中依赖注入的种类大体可以分为三类
- 构造方法注入:在构造方法参数中注入依赖类。
- 多实例非构造方法注入:通过类变量注入,并且注入的对象是多实例的。
- 单实例非构造方式注入:通过类变量注入,并且注入的对象是单实例的
在spring-ioc的实现中,前两种是没有办法解决依赖注入的,但是第三种可以解决,接下来会分析解决办法。
4,spring如何解决循环依赖
spring依赖注入会经过两个步骤完成
(1)创建本实例对象:创建当前的bean实例对象
(2)依赖注入:创建当前对象的依赖的对象实例,并注入到当前对象中
单实例的话,spring会在第一步将这个“半成品”对象放到缓存中,那么如果需要再次使用的话就可以在这个缓存中获取这个半成品的对象,而不需要重复的创建,同时也解决了循环依赖的问题
那么现在看一下为什么构造方法注入和多实例非构造方法注入不可以?首先构造方法注入这种形式在依赖注入的时候是没有“创建本实例对象”这一步的所以也无法缓存“半成品对象",而多实例非构造方法注入这种形式的每一个对象都是新的对象,如果出现循环依赖的话,那出现的结果就是创建无限多的对象,最终导致内存爆炸了。