Spring5源码 - 09 循环依赖解读

文章目录

Spring5源码 - 09 循环依赖解读


什么是循环依赖

举个简单的例子

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

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


模拟循环依赖的问题

Spring5源码 - 09 循环依赖解读

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;
	}
}

【运行结果】

Spring5源码 - 09 循环依赖解读


分析下原因

Spring5源码 - 09 循环依赖解读


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

Spring5源码 - 09 循环依赖解读

上一篇:13.注解实现自动装配


下一篇:Spring常用依赖及注解的使用