系列文章目录
第一篇 spring源码解析之扩展原理BeanFactoryPostProcessor和BeanDefinitionPostProcessor和ApplicationListener
第二篇 spring bean的实例化过程
第三篇 spring容器创建准备的前期工作源码分析
第四篇 spring ioc源码解析之解决循环依赖
第五篇 spring aop源码分析之代理对象的创建
spring ioc源码解析之解决循环依赖
案例
package com.yemuxia.ioc15;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(value = {TestService.class})
@ComponentScan(basePackages = "com.yemuxia.ioc15")
public class AppConfig {
@Bean
public TestDataSource testDataSource() {
return new TestDataSource();
}
}
package com.yemuxia.ioc15;
public class TestDataSource {
public TestDataSource() {
System.out.println("TestDataSource");
}
}
package com.yemuxia.ioc15;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@Repository
//@Scope(value = "prototype")
public class TestDao {
private TestDataSource testDataSource;
public TestDao(TestDataSource testDataSource) {
this.testDataSource = testDataSource;
System.out.println("本类的DataSource"+this.testDataSource);
}
}
package com.yemuxia.ioc15;
import org.springframework.stereotype.Controller;
@Controller
public class TestController {
}
package com.yemuxia.ioc15;
public class TestService {
public TestService() {
System.out.println("我是testService的构造方法");
}
}
package com.yemuxia.ioc15;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainClass {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(ctx.getBean(TestDao.class));
System.out.println(ctx.getBean(TestDao.class));
TestDao testDao = (TestDao) ctx.getBean("testDao");
System.out.println(testDao);
}
}
总结getBean的完整流程
Spring循环依赖的案例
基于属性的循环依赖
package com.yemuxia.ioc17;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class InstanceA {
@Autowired
private InstanceB instanceB;
// @Autowired
public InstanceA(InstanceB instanceB) {
this.instanceB = instanceB;
}
public InstanceA() {
System.out.println("InstanceA实例化");
}
}
package com.yemuxia.ioc17;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class InstanceB {
@Autowired
private InstanceA instanceA;
// @Autowired
public InstanceB(InstanceA instanceA) {
this.instanceA = instanceA;
}
public InstanceB() {
System.out.println("InstanceB实例化");
}
}
package com.yemuxia.ioc17;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.yemuxia.ioc17"})
public class MainConfig {
}
package com.yemuxia.ioc17;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainClass {
public static void main(String[] args) {
//创建IOC容器
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
}
}
构造器参数循环依赖
将实例A和实例B两个类修改成如下
package com.yemuxia.ioc17;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class InstanceA {
// @Autowired
private InstanceB instanceB;
@Autowired
public InstanceA(InstanceB instanceB) {
this.instanceB = instanceB;
}
public InstanceA() {
System.out.println("InstanceA实例化");
}
}
package com.yemuxia.ioc17;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class InstanceB {
// @Autowired
private InstanceA instanceA;
@Autowired
public InstanceB(InstanceA instanceA) {
this.instanceA = instanceA;
}
public InstanceB() {
System.out.println("InstanceB实例化");
}
}
总结
上述案例可知, Spring解决的循环依赖就是指属性的循环依赖
通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。
Spring的三级缓存
- 一级缓存:singletonObjects里面存放的是初始化之后的单例对象;
- 二级缓存:earlySingletonObjects中存放的是一个已完成实例化未完成初始化的早期单例对象;
- 三级缓存:singletonFactories中存放的是ObjectFactory对象,此对象的getObject方法返回值即刚完成实例化还未开始初始化的单例对象。
- 所以先后顺序是,单例对象先存在于singletonFactories中,后存在于earlySingletonObjects中,最后初始化完成后放入singletonObjects中。
Spring是如何解决循环依赖的
Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题。