创建过程图
spring在容器的启动创建阶段,对单例Bean等会默认进行实例的创建,其实就是获取需要创建实例的BeanName,调用getBean方法对其进行创建,只不过就是没有接收返回的参数而已,只是为了Bean的实例化,因为在Bean实例化过程的最后将Bean实例已经放进了集合中了,当再次调用getBean时就直接从集合中获取了,不再执行创建代码了
循环依赖
集合
spring对于循环依赖的处理就是使用了四个集合,包括:
- 实例正在创建流程中集合,实例创建流程前将BeanName放到该集合中,表示此Bean开始创建了。实例创建完成并且填充属性等流程处理后,BeanName从集合中移除,表示Bean实例创建完成
- 实例创建完成集合,当Bean实例通过反射使用spring推断的构造函数newInstance()创建实例后,将BeanName和实例放到集合中,此时Bean实例是原始Bean实例,可作为解决依赖的重要一环,因为这时Bean实例已经创建,但是属性没有填充,也就是没有解析依赖
- 发生循环依赖集合,当一个Bean的依赖链中有Bean又依赖了此Bean,这时就发生了循环依赖,spring这时会从第二步的集合中取出,第二步集合中放的是实例工厂对象,取出后调用获取方法,此方法会执行后置处理器,返回原始Bean实例,也有可能会返回的是代理,这样,循环依赖就解决了
- Bean实例集合,此集合中存放已经通过Bean实例创建流程创建好的实例,实例属性已经填充完,这个集合主要在Bean实例创建流程走之前,获取一下,不存在的话才进行创建流程,其实此集合对于循环依赖的解决没有发挥作用,但是这个集合也贯穿了整个流程,也可以算是一个处理集合吧
这几个集合,在Bean实例创建流程中在不同的时机对其进行增删操作,以此来解决循环依赖,同时spring可以调节可解决的循环依赖,有些循环依赖是spring处理不了的,例如原型模式Bean的循环依赖,因为原型Bean每次调用都是新实例,所以不能用集合来处理,这个就是不可调节的循环依赖
循环依赖代码
依赖关系是: demo依赖demo2,demo2依赖demo3,demo3依赖demo
这里的示例使用了三个类的循环依赖链,其实循环依赖链有两个类就可以,无论两个还是多个,原理是一样的
DemoService
@Component
public class DemoService {
@Autowired
DemoService2 demoService2;
}
DemoService2
@Component
public class DemoService2 {
@Autowired
DemoService3 demoService3;
}
DemoService3
@Component
public class DemoService3 {
@Autowired
DemoService demoService;
}
话解
创建A实例,标识A正在创建中,创建实例(未填充属性),放进实例已创建集合,解析依赖 -> 创建B实例,标识B正在创建中,创建实例(未填充属性),放进实例已创建集合,解析依赖 -> 创建C实例,标识C正在创建中,创建实例(未填充属性),放进实例已创建集合,解析依赖 -> 依赖A,从实例已创建集合中取出 -> 实例C创建完成 ->实例B创建完成 ->实例A创建完成
图解
图解中画的并不代表全部,有些对循环依赖解决关系不大的流程这里就没画出来