spring 解决循环依赖

先上一个调用栈的图:

我的代码结构是:

@Component
public class UserServiceImpl {

	@Autowired
	private ITest test1;

	public String hello(){
		test1.sayHello();
		System.out.println("hello world");
		return  "hello";
	}

}


/**
 * 
 * @since 2019-06-11 11:09
 */
@Component
public class Test1 implements ITest {

	@Autowired
	UserServiceImpl userService;

	@Override
	public void sayHello() {
		System.out.println("hello Test1");
	}
}


public class Mytest {

	public static void main(String[] args) {
		//System.out.println(111);
		//AnnotationC
		AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext();
		configApplicationContext.scan("com.test");
		//configApplicationContext.register(UserServiceImpl.class);
		configApplicationContext.refresh();


	
		UserServiceImpl o = (UserServiceImpl)configApplicationContext.getBean("userServiceImpl");

		System.out.println(o.hello());



	}
}

        从调用栈看,spring在执行UserServiceImpl的初始化(因为我打断点的条件是beanName.equals("userServiceImpl")),这里简单说下,spring初始化bean生命周期,上面的调用栈已经到了spring容器初始的尾声,已经执行到了refresh方法里面的finishBeanFactoryInitialization(初始化剩余的bean,简单理解其实就是用户加了service或component那些bean)方法,在finishBeanFactoryInitialization方法前,其实执行了好多工作,比如执行BeanFactoryPostProcessors,注册BeanPostProcessors等,至于这些的用途,不在这里说明。

        再从堆栈的preInstantiateSingletons看,里面是一个for循环去把beanDefinitionNames里面的bean定义实例化,首先是调用getBean方法,然后第一次调用doGetBean,在这个方法里头,先尝试去重cache里面找提前曝光的对象Object sharedInstance = getSingleton(beanName);第一次调用肯定没有,就继续走下去,第一次调用getSingleton方法,先从singletonObjects里面找有没有已经创建好的bean,如果没有就继续往后走,这里方法有个beforeSingletonCreation(beanName);方法,这个方法有个list(singletonsCurrentlyInCreation)用于存放这个beanname,用于判断bean是否正在创建,然后就执行createBean方法,这里里头有执行好几个beanPostProcessor,然后就第一次执行populateBean,这个方法是用于填充属性,是一个继承InstantiationAwareBeanPostProcessorAdapter的AutowiredAnnotationBeanPostProcessor的postProcessProperties方法中完成,里面执行对象的inject(注入),当遇到要注入class,还会判断是根据type,和name注入,主要在DefaultListableBeanFactory中的doResolveDependency完成,好了,到这里,如果返现Test baen没有创件就执行getBean方法,这里就有点像递归了,然后就执行Test的创建,流程和上面一样,关键是在执行Test的populateBean填充属性的时候,去填充UserServiceImpl的时候,会首先判断该bean是否正在创建,由于上面已经把这个bean放在一个正在创建的list(singletonsCurrentlyInCreation)中,最终会走到上图堆栈的最后一个方法getEarlyBeanReference,把提前曝光的对象拿出来,至于这个getEarlyBeanReference所在的对象什么时候放进去,这个就要看前面代码,这里不贴出来。在此已经基本完成解决循环引用的过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值