Spring循环的问题模拟
- 先准备两个实例
package com.sw.swtest.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 8:45
* @description :
*/
@Component
public class InstanceA {
@Autowired
private InstanceB instanceB;
public InstanceB getInstB() {
return instanceB;
}
public void setInstB(InstanceB instB) {
this.instanceB = instB;
}
public InstanceA() {
System.out.println("InstanceA的构造方法");
}
@Override
public String toString() {
return "InstanceA{}";
}
}
package com.sw.swtest.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 8:46
* @description :
*/
@Component
public class InstanceB {
@Autowired
private InstanceA instanceA;
public InstanceA getInstanceA() {
return instanceA;
}
public void setInstanceA(InstanceA instanceA) {
this.instanceA = instanceA;
}
public InstanceB() {
System.out.println("InstanceB的构造方法");
}
@Override
public String toString() {
return "InstanceB{}";
}
}
2.会出现循环依赖的现象,尽量的去模拟Spring(我模拟的比较简单)
package com.sw.swtest.spring;
import org.springframework.beans.factory.ObjectFactory;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 14:15
* @description : Spring解决循环依赖(三级缓存)模拟
*/
public class MainStart {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//一级缓存
public static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
//二级缓存 (将纯熟bean和纯净bean分离,避免读取到不完整的bean)
public static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
//三级缓存
public static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();
//循环依赖标识
public static Set<String> singletonsCurrentlyInCreation = new HashSet<>();
/**
* 读取bean定义,在Spring中肯定是根据配置动态扫描的
*/
public static void loadBeanDefinition() {
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//Spring中会 注册bean的后置处理器 registerBeanPostProcessors
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//会先创建A
getBean(key);
}
}
//获取bean
private static Object getBean(String beanName) throws Exception {
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
//通过无参构造函数实例化(Spring中可以通过工厂或者有参构造函数)
Object instanceBean = beanClass.newInstance();
//属性赋值
//先拿到所有的属性值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//找到属性值上有@Autowired注解的属性
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if (annotation != null) {
//打开私有属性的访问权限
declaredField.setAccessible(true);
//instanceB (Spring中除了byName, 还可以byType, byConstruct)
String name = declaredField.getName();
Object fieldObject = getBean(name);
//Field将指定对象参数上此对象表示的字段设置为指定的新值
declaredField.set(instanceBean, fieldObject);
}
}
//初始化(init-method等等,三种配置方式,循环依赖的案例暂时忽略初始化方法)
//添加到一级缓存
singletonObjects.put(beanName, instanceBean);
return instanceBean;
}
}
- 运行结果如下: 死循环
循环依赖现象: 循环创建Bean的时候,BeanA依赖于BeanB,BeanB又依赖于BeanA,重复创建死循环
package com.sw.swtest.spring;
import org.springframework.beans.factory.ObjectFactory;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 14:15
* @description : Spring解决循环依赖(三级缓存)模拟
*/
public class MainStart {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//一级缓存
public static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
//二级缓存 (将纯熟bean和纯净bean分离,避免读取到不完整的bean)
public static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
//三级缓存
public static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();
//循环依赖标识
public static Set<String> singletonsCurrentlyInCreation = new HashSet<>();
/**
* 读取bean定义,在Spring中肯定是根据配置动态扫描的
*/
public static void loadBeanDefinition() {
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//Spring中会 注册bean的后置处理器 registerBeanPostProcessors
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//会先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
System.out.println(instanceA);
}
//获取bean
private static Object getBean(String beanName) throws Exception {
//给循环依赖添加出口
Object singleton = getSingleton(beanName);
if(singleton!= null){
return singleton;
}
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
//通过无参构造函数实例化(Spring中可以通过工厂或者有参构造函数)
Object instanceBean = beanClass.newInstance();
//添加到一级缓存
singletonObjects.put(beanName, instanceBean);
//属性赋值
//先拿到所有的属性值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//找到属性值上有@Autowired注解的属性
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if (annotation != null) {
//打开私有属性的访问权限
declaredField.setAccessible(true);
//instanceB (Spring中除了byName, 还可以byType, byConstruct)
String name = declaredField.getName();
Object fieldObject = getBean(name);
//Field将指定对象参数上此对象表示的字段设置为指定的新值
declaredField.set(instanceBean, fieldObject);
}
}
//初始化(init-method等等,三种配置方式,循环依赖的案例暂时忽略初始化方法)
return instanceBean;
}
public static Object getSingleton(String beanName){
//先从一级缓存中拿
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
}
return null;
}
}
解决循环依赖: 就是给循环依赖添加一个出口getSingleton(), 如果一级缓存中有就返回一级缓存中的对象,如果没有返回空,
(注意:放入一级缓存的时机需要调整到属性赋值之前)
流程: beanA 实例化==>beanA放入一级缓存 ==>属性赋值 ==>beanB 实例化 ==> beanB放入一级缓存 ==>属性赋值获取beanA 此时拿到的beanA就是不完整的bean
结论: 一级缓存就可以解决循环依赖,但是并发时会出现问题,会拿到不完整的bean(如果硬要钻牛角尖的话,一级缓存就可以解决循环依赖了,加锁解决并发也可以,但是毕竟是Spring,职能划分很明确,因此才有了二级缓存)
面试(美团): Spring是怎么避免读取到不完整的bean?
答: Spring引入了二级缓存earlySingletonObjects , 为了将成熟bean和纯净bean分离开,避免读取到不完整的bean, 只实例化没有属性赋值的纯净bean就存入二级缓存中,属性赋值初始化之后的bean存入一级缓存
package com.sw.swtest.spring;
import org.springframework.beans.factory.ObjectFactory;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 14:15
* @description : Spring解决循环依赖(三级缓存)模拟
*/
public class MainStart {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//一级缓存
public static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
//二级缓存 (将纯熟bean和纯净bean分离,避免读取到不完整的bean)
public static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
//三级缓存
public static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();
//循环依赖标识
public static Set<String> singletonsCurrentlyInCreation = new HashSet<>();
/**
* 读取bean定义,在Spring中肯定是根据配置动态扫描的
*/
public static void loadBeanDefinition() {
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//Spring中会 注册bean的后置处理器 registerBeanPostProcessors
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//会先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
System.out.println(instanceA);
}
//获取bean
private static Object getBean(String beanName) throws Exception {
//给循环依赖添加出口
Object singleton = getSingleton(beanName);
if(singleton!= null){
return singleton;
}
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
//通过无参构造函数实例化(Spring中可以通过工厂或者有参构造函数)
Object instanceBean = beanClass.newInstance();
//添加到二级缓存
earlySingletonObjects.put(beanName, instanceBean);
//属性赋值
//先拿到所有的属性值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//找到属性值上有@Autowired注解的属性
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if (annotation != null) {
//打开私有属性的访问权限
declaredField.setAccessible(true);
//instanceB (Spring中除了byName, 还可以byType, byConstruct)
String name = declaredField.getName();
Object fieldObject = getBean(name);
//Field将指定对象参数上此对象表示的字段设置为指定的新值
declaredField.set(instanceBean, fieldObject);
}
}
//初始化(init-method等等,三种配置方式,循环依赖的案例暂时忽略初始化方法)
//添加到一级缓存
singletonObjects.put(beanName, instanceBean);
return instanceBean;
}
public static Object getSingleton(String beanName){
//先从一级缓存中拿
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
//一级缓存拿不到从二级缓存中拿
}else if (earlySingletonObjects.containsKey(beanName)){
return earlySingletonObjects.get(beanName);
}
return null;
}
}
实例化后属性赋值之前的纯净bean放入二级缓存,初始化之后的bean放入一级缓存
getSingleton会先从一级缓存中获取,一级缓存中没有才会从二级缓存中拿
结论: 二级缓存是为了解决并发场景下的循环依赖问题,将成熟bean和纯净bean分离开,避免读取到不完整的bean
问题: 第三级缓存的作用是什么? AOP或者是动态代理?
答: 二级缓存其实就可以解决AOP
准备动态代理相关配置
package com.sw.swtest.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 16:51
* @description :
*/
public class JdkDynamicProxy implements InvocationHandler {
private Object target;
public JdkDynamicProxy(Object target) {
this.target = target;
}
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("测试");
return method.invoke(target,args);
}
}
通过后置处理器的方式,解析切点的逻辑直接忽略了,这里只做了简单的模拟,只判断是不是InstanceA
package com.sw.swtest.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 16:49
* @description :
*/
@Component
public class JdkProxyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
// 假设A被切点命中 需要创建代理
if(bean instanceof InstanceA) {
JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(bean);
return jdkDynamicProxy.getProxy();
}
return bean;
}
}
面试: Spring的getBean在什么时候创建动态代理?
答: 如果没有发生循环依赖,Spring会在初始化之后创建动态代理,但是如果发生循环依赖,Spring会在实例化之后就创建动态代理
package com.sw.swtest.spring;
import org.springframework.beans.factory.ObjectFactory;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 14:15
* @description : Spring解决循环依赖(三级缓存)模拟
*/
public class MainStart {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//一级缓存
public static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
//二级缓存 (将纯熟bean和纯净bean分离,避免读取到不完整的bean)
public static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
//三级缓存
public static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();
//循环依赖标识
public static Set<String> singletonsCurrentlyInCreation = new HashSet<>();
/**
* 读取bean定义,在Spring中肯定是根据配置动态扫描的
*/
public static void loadBeanDefinition() {
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//Spring中会 注册bean的后置处理器 registerBeanPostProcessors
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//会先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
System.out.println(instanceA);
}
//获取bean
private static Object getBean(String beanName) throws Exception {
//给循环依赖添加出口
Object singleton = getSingleton(beanName);
if(singleton!= null){
return singleton;
}
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
//通过无参构造函数实例化(Spring中可以通过工厂或者有参构造函数)
Object instanceBean = beanClass.newInstance();
//创建动态代理(Spring里面是后置处理器的方式)
instanceBean = new JdkProxyBeanPostProcessor().getEarlyBeanReference(instanceBean,beanName);
//添加到二级缓存
earlySingletonObjects.put(beanName, instanceBean);
//属性赋值
//先拿到所有的属性值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//找到属性值上有@Autowired注解的属性
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if (annotation != null) {
//打开私有属性的访问权限
declaredField.setAccessible(true);
//instanceB (Spring中除了byName, 还可以byType, byConstruct)
String name = declaredField.getName();
Object fieldObject = getBean(name);
//Field将指定对象参数上此对象表示的字段设置为指定的新值
declaredField.set(instanceBean, fieldObject);
}
}
//初始化(init-method等等,三种配置方式,循环依赖的案例暂时忽略初始化方法)
//添加到一级缓存
singletonObjects.put(beanName, instanceBean);
return instanceBean;
}
public static Object getSingleton(String beanName){
//先从一级缓存中拿
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
//一级缓存拿不到从二级缓存中拿
}else if (earlySingletonObjects.containsKey(beanName)){
return earlySingletonObjects.get(beanName);
}
return null;
}
}
其实利用二级缓存就已经解决动态代理的问题了,但是这种写法会导致普通bean哪怕没有出现循环依赖,也会在实例化之后就创建了动态代理, Spring还是希望正常的bean能在初始化之后创建动态代理,只在出现循环依赖的时候才会在实例化之后创建动态代理
问题: 如何判断当前是不是循环依赖?
答: 二级缓存中只要存在该bean,就出现循环依赖(仔细品味)
在getSinleton()方法中,如果二级缓存中有值,那么就代表出现循环依赖
package com.sw.swtest.spring;
import org.springframework.beans.factory.ObjectFactory;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 14:15
* @description : Spring解决循环依赖(三级缓存)模拟
*/
public class MainStart {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//一级缓存
public static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
//二级缓存 (将纯熟bean和纯净bean分离,避免读取到不完整的bean)
public static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
//三级缓存
public static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();
//循环依赖标识
public static Set<String> singletonsCurrentlyInCreation = new HashSet<>();
/**
* 读取bean定义,在Spring中肯定是根据配置动态扫描的
*/
public static void loadBeanDefinition() {
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//Spring中会 注册bean的后置处理器 registerBeanPostProcessors
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//会先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
System.out.println(instanceA);
}
//获取bean
private static Object getBean(String beanName) throws Exception {
//给循环依赖添加出口
Object singleton = getSingleton(beanName);
if(singleton!= null){
return singleton;
}
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
//通过无参构造函数实例化(Spring中可以通过工厂或者有参构造函数)
Object instanceBean = beanClass.newInstance();
//添加到二级缓存
earlySingletonObjects.put(beanName, instanceBean);
//属性赋值
//先拿到所有的属性值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//找到属性值上有@Autowired注解的属性
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if (annotation != null) {
//打开私有属性的访问权限
declaredField.setAccessible(true);
//instanceB (Spring中除了byName, 还可以byType, byConstruct)
String name = declaredField.getName();
Object fieldObject = getBean(name);
//Field将指定对象参数上此对象表示的字段设置为指定的新值
declaredField.set(instanceBean, fieldObject);
}
}
//初始化(init-method等等,三种配置方式,循环依赖的案例暂时忽略初始化方法)
//添加到一级缓存
singletonObjects.put(beanName, instanceBean);
return instanceBean;
}
public static Object getSingleton(String beanName){
//先从一级缓存中拿
if(singletonObjects.containsKey(beanName)){
return singletonObjects.get(beanName);
//一级缓存拿不到从二级缓存中拿
}else if (earlySingletonObjects.containsKey(beanName)){
//代表出现循环依赖
//创建动态代理(Spring里面是后置处理器的方式)
Object obj = new JdkProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.get(beanName), beanName);
//再放到二级缓存中去
earlySingletonObjects.put(beanName,obj);
return earlySingletonObjects.get(beanName);
}
return null;
}
}
Spring中创建动态代理是在后置处理器中实现的,是不建议直接放在getBean()里面实现的,所以引入了三级缓存 singletonFactories.
所以:
1.AOP的代码可以继续放在实例化之后,添加二级缓存之前, 但是这样需要用函数式接口的钩子方法来实现,所以三级缓存map里存的其实就是函数式接口
2.如果某个bean实例需要动态代理,那么二级缓存里存原实例的bean还是动态代理呢?肯定是动态代理吧, 那存入二级缓存这一步就必须在动态代理之后,所以放在getSingleton()函数式接口回调完成,拿到动态代理之后
3.getSingleton()里判断如果发生循环依赖,那么就需要借助二级缓存来获取纯净bean,所以就需要从二级缓存中去获取
4.getSingleton() 需要先从一级缓存中获取bean,如果拿不到,需要从二级缓存中获取bean,如果拿不到,再从三级缓存中获取bean,获取到以后放入二级缓存
5.本来可以在实例化之后直接放入二级缓存,所以可以通过二级缓存中是否存在bean实例判断是否发生循环依赖的, 但是现在, 因为二级缓存的put是在动态代理之后,getSingleton()之中, 所以就没办法通过二级缓存来判断是否发生循环依赖, 所以引入了正在创建的标识singletonsCurrentlyInCreation
结论1: 一二级缓存就已经解决了AOP动态代理问题,所以引入三级缓存的目的是为了一种规范,为了解耦代码, 三级缓存解决了循环依赖,但是不是为了解决循环依赖而存在的
结论2: getBean(A) —> getSingleton(A)–> 一级缓存没有 && 没有正在创建beanA —> 标记正在创建A—>A的函数式接口放入三级缓存—>实例化A —> 属性赋值beanB—>getBean(B)—>getSingleton(B)—>一级缓存没有&&没有正在创建beanB —> 标记正在创建B —>B的函数式接口放入三级缓存 —> 实例化B —>属性赋值beanA—>getBean(A) —> 一级缓存没有 && 正在创建beanA —> 二级缓存没有—>A三级缓存判断存在 —>创建动态代理 —>代理A放入二级缓存 —>初始化A —> 二级缓存存在代理A,将代理A放入一级缓存 —> 初始化B --> 将B放入一级缓存
package com.sw.swtest.spring;
import org.springframework.beans.factory.ObjectFactory;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author MissHeaven
* @version : 1.0
* @date : 2023/1/9 14:15
* @description : Spring解决循环依赖(三级缓存)模拟
*/
public class MainStart {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//一级缓存
public static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
//二级缓存 (将纯熟bean和纯净bean分离,避免读取到不完整的bean)
public static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
//三级缓存
public static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();
//循环依赖标识
public static Set<String> singletonsCurrentlyInCreation = new HashSet<>();
/**
* 读取bean定义,在Spring中肯定是根据配置动态扫描的
*/
public static void loadBeanDefinition() {
RootBeanDefinition aBeanDefinition = new RootBeanDefinition(InstanceA.class);
RootBeanDefinition bBeanDefinition = new RootBeanDefinition(InstanceB.class);
beanDefinitionMap.put("instanceA", aBeanDefinition);
beanDefinitionMap.put("instanceB", bBeanDefinition);
}
public static void main(String[] args) throws Exception {
//加载beanDefinition
loadBeanDefinition();
//Spring中会 注册bean的后置处理器 registerBeanPostProcessors
//循环创建bean
for (String key : beanDefinitionMap.keySet()) {
//会先创建A
getBean(key);
}
InstanceA instanceA = (InstanceA) getBean("instanceA");
System.out.println(instanceA);
}
//获取bean
private static Object getBean(String beanName) throws Exception {
//给循环依赖添加出口
Object singleton = getSingleton(beanName);
if(singleton!= null){
return singleton;
}
//标记正在创建
if(!singletonsCurrentlyInCreation.contains(beanName)){
singletonsCurrentlyInCreation.add(beanName);
}
//实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
//通过无参构造函数实例化(Spring中可以通过工厂或者有参构造函数)
Object instanceBean = beanClass.newInstance();
//放入三级缓存,创建动态代理(Spring里面是后置处理器的方式)
Object finalInstanceBean = instanceBean;
singletonFactories.put(beanName, () -> new JdkProxyBeanPostProcessor().getEarlyBeanReference(finalInstanceBean, beanName));
//属性赋值
//先拿到所有的属性值
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//找到属性值上有@Autowired注解的属性
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if (annotation != null) {
//打开私有属性的访问权限
declaredField.setAccessible(true);
//instanceB (Spring中除了byName, 还可以byType, byConstruct)
String name = declaredField.getName();
Object fieldObject = getBean(name);
//Field将指定对象参数上此对象表示的字段设置为指定的新值
declaredField.set(instanceBean, fieldObject);
}
}
//初始化(init-method等等,三种配置方式,循环依赖的案例暂时忽略初始化方法)
//由于递归完后,A还是原实例,所以需要从二级缓存中拿代理放入一级缓存,来保证代理在bean容器中生效
if(earlySingletonObjects.containsKey(beanName)){
instanceBean=earlySingletonObjects.get(beanName);
}
//添加到一级缓存
singletonObjects.put(beanName, instanceBean);
//移除二级缓存和三级缓存
return instanceBean;
}
public static Object getSingleton(String beanName){
//先从一级缓存中拿
Object bean = singletonObjects.get(beanName);
//如果一级缓存中没有,且正在创建,出现循环依赖
if(bean == null && singletonsCurrentlyInCreation.contains(beanName)){
//从二级缓存中拿
bean = earlySingletonObjects.get(beanName);
if(bean == null){
//如果二级缓存中没有则从三级缓存中拿
ObjectFactory factory = singletonFactories.get(beanName);
if(factory != null){
//回调钩子方法,拿到动态代理
bean = factory.getObject();
earlySingletonObjects.put(beanName,bean);
}
}
}
return bean;
}
}