Java教程

Spring5源码 - 09 循环依赖解读

本文主要是介绍Spring5源码 - 09 循环依赖解读,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 什么是循环依赖
  • 模拟循环依赖的问题
  • Spring 的循环依赖解决方案(三级缓存)

在这里插入图片描述


什么是循环依赖

举个简单的例子

A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。

或者是 A 依赖 B,B 依赖 C,C 又依赖 A,同样的 也是循环依赖


模拟循环依赖的问题

在这里插入图片描述

package com.artisan.cycleDepend;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class A {

  @Autowired
  private B b;

	@PostConstruct
	public void init(){
		System.out.println("A");
	}
}

import javax.annotation.PostConstruct;

@Component
public class B {

	@Autowired
	private A a ;

	@PostConstruct
	public void init(){
		System.out.println("A");
	}
}

【测试代码】

package com.artisan.cycleDepend;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 模拟循环依赖的问题
 */
public class CycleDependTest {

	private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

	// 一级缓存
	private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();

	public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		// 模拟Spring 的 解析对象为 BeanDefinition 并放到 BeanDefinitionMap中
		RootBeanDefinition  a = new RootBeanDefinition(A.class);
		RootBeanDefinition  b = new RootBeanDefinition(B.class);

		beanDefinitionMap.put("a",a);
		beanDefinitionMap.put("b",b);


		// 模拟Spring 的 getBean  循环创建Bean
		for (String beanName : beanDefinitionMap.keySet()){
			getBean(beanName);
		}

	}


	public static Object getBean(String beanName) throws IllegalAccessException, InstantiationException {

		// 实例化
		RootBeanDefinition  beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
		Class<?> beanClass = beanDefinition.getBeanClass();
		Object o = beanClass.newInstance();


		// 属性填充

		// 获取声明的字段
		Field[] declaredFields = o.getClass().getDeclaredFields();
		// 遍历
		for (Field declaredField : declaredFields) {
			// 检查是否有Autowired注解
			Autowired annotation = declaredField.getAnnotation(Autowired.class);
			if (annotation != null){
				// private属性 需要设置为true
				declaredField.setAccessible(true);
				// 获取属性的名字
				String name = declaredField.getName();
				// 递归调用getBean获取实例
				Object bean = getBean(name);
				// 字段设置属性
				 declaredField.set(o,bean);

			}

		}

		// 初始化  init-method 。。。。

		// 存入一级缓存
		singletonObjects.put(beanName,o);

		return o;
	}
}

【运行结果】

在这里插入图片描述


分析下原因

在这里插入图片描述


Spring 的循环依赖解决方案(三级缓存)

在这里插入图片描述

这篇关于Spring5源码 - 09 循环依赖解读的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!