GVKun编程网logo

Spring5 依赖注入和循环依赖处理(spring依赖注入原理)

18

在这篇文章中,我们将带领您了解Spring5依赖注入和循环依赖处理的全貌,包括spring依赖注入原理的相关情况。同时,我们还将为您介绍有关.net–依赖注入解决循环依赖关系、3.1spring5源码

在这篇文章中,我们将带领您了解Spring5 依赖注入和循环依赖处理的全貌,包括spring依赖注入原理的相关情况。同时,我们还将为您介绍有关.net – 依赖注入解决循环依赖关系、3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖、3.2spring源码系列----循环依赖源码分析 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖、3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析的知识,以帮助您更好地理解这个主题。

本文目录一览:

Spring5 依赖注入和循环依赖处理(spring依赖注入原理)

Spring5 依赖注入和循环依赖处理(spring依赖注入原理)

//TODO 依赖注入待补充


循环依赖处理

怎么检测是否存在循环依赖

检测循环依赖相对比较容易,Bean 在创建的时候可以给该 Bean 打标,如果递归调用回来发现正在创建中的话,即说明了循环依赖了。

进行处理

Spring 的单例对象的初始化主要分为三步 (前在 AbstractAutowireCapableBeanFactory#doCreateBean):

  1. createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象
  2. populateBean:填充属性,这一步主要是多 Bean 的依赖属性进行填充
  3. initializeBean:初始化 Bean。

从上面单例 bean 的初始化可以知道: 依赖主要发生在第一、二步,也就是构造器依赖和 field 依赖。如果发生了循环依赖,构造器方式无解,field 循环依赖可以通过将初始化分为两个阶段进行解决。即先对对象实例化,待循环依赖的对象属性填充完之后,再进行自身的属性填充。

对于单例对象来说,在 Spring 容器整个生命周期内,有且只有一个对象,所以很容易想到对象应该存在 Cache 中。同时,Spring 为了解决单例的循环依赖问题,使用了三个容器做缓存在 DefaultSingletonBeanRegistry 对象中进行保存:

  1. singletonObjects : 用于存放完全初始化好的 bean
  2. earlySingletonObjects:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
  3. singletonFactories:存放 bean 工厂对象,用于解决循环依赖
在 populateBean () 中进行依赖注入 (Autowired/Resource)

AbstractAutowireCapableBeanFactory

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// ...
	
	// 是否有注入的Bean属性
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		//getBeanPostProcessors 返回一系列BeanPostProcessor处理器
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				//
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
	}
	//...

AutowiredAnnotationBeanPostProcessor

/**
 * 属性注入处理
 */
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
		// 进行属性的注入
		metadata.inject(bean, beanName, pvs);
	}
	catch (BeanCreationException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

InjectionMetadata

/**
 * 注入
 */
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
		(checkedElements != null ? checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
		for (InjectedElement element : elementsToIterate) {
			if (logger.isTraceEnabled()) {
				logger.trace("Processing injected element of bean ''" + beanName + "'': " + element);
			}
			//调用注入
			element.inject(target, beanName, pvs);
		}
	}
}

AutowiredAnnotationBeanPostProcessor

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Field field = (Field) this.member;
	//要被注入的对象
	Object value;
	if (this.cached) {
		value = resolvedCachedArgument(beanName, this.cachedFieldValue);
	}
	else {
		DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
		desc.setContainingClass(bean.getClass());
		Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
		Assert.state(beanFactory != null, "No BeanFactory available");
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		synchronized (this) {
			if (!this.cached) {
				if (value != null || this.required) {
					this.cachedFieldValue = desc;
					registerDependentBeans(beanName, autowiredBeanNames);
					if (autowiredBeanNames.size() == 1) {
						String autowiredBeanName = autowiredBeanNames.iterator().next();
						if (beanFactory.containsBean(autowiredBeanName) &&
							beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
							this.cachedFieldValue = new ShortcutDependencyDescriptor(
								desc, autowiredBeanName, field.getType());
						}
					}
				}
				else {
					this.cachedFieldValue = null;
				}
				this.cached = true;
			}
		}
	}
	if (value != null) {
		ReflectionUtils.makeAccessible(field);
		field.set(bean, value);
	}
}
}

DefaultListableBeanFactory#doResolveDependency 循环依赖解决

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
								  @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
			return shortcut;
		}

		Class<?> type = descriptor.getDependencyType();
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
		if (value != null) {
			if (value instanceof String) {
				String strVal = resolveEmbeddedValue((String) value);
				BeanDefinition bd = (beanName != null && containsBean(beanName) ?
									 getMergedBeanDefinition(beanName) : null);
				value = evaluateBeanDefinitionString(strVal, bd);
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			try {
				return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
			}
			catch (UnsupportedOperationException ex) {
				// A custom TypeConverter which does not support TypeDescriptor resolution...
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}
		}

		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
		if (multipleBeans != null) {
			return multipleBeans;
		}

		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		if (matchingBeans.size() > 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
					return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
				}
				else {
					// In case of an optional Collection/Map, silently ignore a non-unique case:
					// possibly it was meant to be an empty collection of multiple regular beans
					// (before 4.3 in particular when we didn''t even look for collection beans).
					return null;
				}
			}
			instanceCandidate = matchingBeans.get(autowiredBeanName);
		}
		else {
			// We have exactly one match.
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
		}
		Object result = instanceCandidate;
		if (result instanceof NullBean) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			result = null;
		}
		if (!ClassUtils.isAssignableValue(type, result)) {
			throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
		}
		return result;
	}
	finally {
		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
	}
}

populateBean 注入属性 doGetBean->getSingleton 删除 bean 缓存

项目推荐:基于 Spring Cloud Alibaba 技术,包含基础功能、OA、支付、营销等模块的分布式微服务开发平台

.net – 依赖注入解决循环依赖关系

.net – 依赖注入解决循环依赖关系

我在各种网站上看过几篇文章,提出通过依赖注入来解决.NET程序集之间的循环依赖关系.这可能会解决构建错误,但它并没有真正解决循环依赖,是吗?对我来说,架构似乎仍然存在逻辑错误.我是疯狂还是别人同意1)这不是DI的恒星使用,2)不是解决循环依赖问题的适当方式吗?
如果您有两个对象之间的循环依赖关系,则表示您需要一个第三个对象,两个对象将依赖这些对象,因此它们将不依赖于彼此.这是一个文章,是您的问题的确切解决方案:

http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/

3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

本次博客的目标

1. 手写spring循环依赖的整个过程

2. spring怎么解决循环依赖

3. 为什么要二级缓存和三级缓存

4. spring有没有解决构造函数的循环依赖

5. spring有没有解决多例下的循环依赖.

一.  什么是循环依赖?

如下图所示: 

 

 A类依赖了B类,同时B类有依赖了A类. 这就是循环依赖,形成了一个闭环

 

 

如上图: A依赖了B,B同时依赖了A和C,C依赖了A. 这也是循环依赖. ,形成了一个闭环

 

那么,如果出现循环依赖,spring是如何解决循环依赖问题的呢?

二. 模拟循环依赖

2.1 复现循环依赖

我们定义三个类:

1. 新增类InstanceA

package com.lxl.www.circulardependencies;

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

@Component
@Scope("prototype")
public class InstanceA {
    @Autowired
    private InstanceB instanceB;

    public InstanceA() {
        System.out.println(调用 instanceA的构造函数);
    }

     InstanceA(InstanceB instanceB) {
        this.instanceB = instanceB;
    }

    void say(){
        System.out.println( I am A);
    }


     InstanceB getInstanceB() {
        return setInstanceB(InstanceB instanceB) {
         instanceB;
    }

}

 

这是InstanceA,里面引用了InstanceB.

 

2. 新增类instanceB

 InstanceB {

    @Autowired
    private InstanceA instanceA;
     InstanceB() {
        System.调用 instanceB的构造函数 InstanceA getInstanceA() {
         instanceA;
    }

     setInstanceA(InstanceA instanceA) {
        this.instanceA = instanceA;
    }



}

 

这是InstanceB,在里面有引用了InstanceA

3:模拟spring是如何创建Bean的

这个在前面已经说过了,首先会加载配置类的后置处理器,将其解析后放入到beanDeFinitionMap中. 然后加载配置类,也将其解析后放入beanDeFinitionMap中. 最后解析配置类. 我们这里直接简化掉前两步,将两个类放入beanDeFinitionMap中. 主要模拟第三步解析配置类. 在解析的过程中,获取bean的时候会出现循环依赖的问题循环依赖.

第一步: 将两个类放入到beanDeFinitionMap中

 MainStart {
    private static Map<String,BeanDeFinition> beanDeFinitionMap = new ConcurrentHashMap<>();

/*
* * 读取bean定义,当然在spring中肯定是根据配置 动态扫描注册的 * * InstanceA和InstanceB都有注解@Component,所以,在spring扫描读取配置类的时候,会把他们两个扫描到BeanDeFinitionMap中. * 这里,我们省略这一步,直接将instanceA和instanceB放到BeanDeFinitionMap中. */ static void loadBeanDeFinitions(){ RootBeanDeFinition aBeanDeFinition = new RootBeanDeFinition(InstanceA.); RootBeanDeFinition bBeanDeFinition = new RootBeanDeFinition(InstanceB.); beanDeFinitionMap.put("instanceA",aBeanDeFinition); beanDeFinitionMap.put("instanceB",bBeanDeFinition); } main(String[] args) throws Exception { // 第一步: 扫描配置类,读取bean定义 loadBeanDeFinitions(); ...... }

 

上面的代码结构很简单,再看一下注释应该就能明白了. 这里就是模拟spring将配置类解析放入到beanDeFinitionMap的过程. 

 

第二步: 循环创建bean

首先,我们已经知道,创建bean一共有三个步骤: 实例化,属性赋值,初始化. 

 

 

 

而在属性赋值的时候,会判断是否引用了其他的Bean,如果引用了,那么需要构建此Bean. 下面来看一下代码

/**
     * 获取bean,根据beanName获取
     */
    static Object getBean(String beanName) throws Exception {*
         * 第一步: 实例化
         * 我们这里是模拟,采用反射的方式进行实例化. 调用的也是最简单的无参构造函数
         */
        RootBeanDeFinition beanDeFinition = (RootBeanDeFinition) beanDeFinitionMap.get(beanName);
        Class<?> beanClass = beanDeFinition.getBeanClass();
         调用无参的构造函数进行实例化
        Object instanceBean = beanClass.newInstance();

       *
         *  第二步: 属性赋值
         *  instanceA这类类里面有一个属性,InstanceB. 所以,先拿到 instanceB,然后在判断属性头上有没有Autowired注解.
         *  注意: 这里我们只是判断有没有Autowired注解. spring中还会判断有没有@Resource注解. @Resource注解还有两种方式,一种是name,一种是type
         
        Field[] declaredFields = beanClass.getDeclaredFields();
        for (Field declaredField: declaredFields) {
             判断每一个属性是否有@Autowired注解
            Autowired annotation = declaredField.getAnnotation(Autowired.);
            if (annotation != null) {
                 设置这个属性是可访问的
                declaredField.setAccessible(true);
                 那么这个时候还要构建这个属性的bean.
                
                 * 获取属性的名字
                 * 真实情况,spring这里会判断,是根据名字,还是类型,还是构造函数来获取类.
                 * 我们这里模拟,所以简单一些,直接根据名字获取.
                 
                String name = declaredField.getName();

                *
                 * 这样,在这里我们就拿到了 instanceB 的 bean
                 
                Object fileObject = getBean(name);

                 为属性设置类型
                declaredField.set(instanceBean,fileObject);
            }
        }


        *
         * 第三步: 初始化
         * 初始化就是设置类的init-method.这个可以设置也可以不设置. 我们这里就不设置了
         */
         instanceBean;
    }

 

我们看到如上代码. 

第一步: 实例化: 使用反射的方式,根据beanName查找构建一个实例bean. 

第二步: 属性赋值: 判断属性中是否有@Autowired属性,如果有这个属性,那么需要构建bean. 我们发现在为InstanceA赋值的时候,里面引用了InstanceB,所以去创建InstanceB,而创建InstanceB的时候,发现里面又有InstanceA,于是又去创建A. 然后以此类推,继续判断. 就形成了死循环. 无法走出这个环. 这就是循环依赖

第三步: 初始化: 调用init-method,这个方法不是必须有,我们这里不模拟了

看看如下图所示

 

 红色部分就形成了循环依赖.

4: 增加一级缓存,解决循环依赖的问题. 

我们知道上面进行了循环依赖了. 其实,我们的目标很简单,如果一个类创建过了,那么就请不要在创建了. 

所以,我们增加一级缓存

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

   static Object getBean(String beanName) throws Exception {

         增加一个出口. 判断实体类是否已经被加载过了
        Object singleton = getSingleton(beanName);
        if (singleton != ) {
             singleton;
        }

        *
         * 第一步: 实例化
         * 我们这里是模拟,1)"> beanClass.newInstance();

        第二步: 放入到一级缓存
         
        singletonObjects.put(beanName,instanceBean);
        *
         *  第三步: 属性赋值
         *  instanceA这类类里面有一个属性,一种是type
          *
         * 第四步: 初始化
         * 初始化就是设置类的init-method.这个可以设置也可以不设置. 我们这里就不设置了
          instanceBean;
    }

 

还是上面的获取bean的流程,不一样的是,这里增加了以及缓存. 当我们获取到bean实例以后,将其放入到缓存中. 下次再需要创建之前,先去缓存里判断,是否已经有了,如果没有,那么再创建. 

这样就给创建bean增加了一个出口. 不会循环创建了.

 

 

如上图所示,在@Autowired的时候,增加了一个出口. 判断即将要创建的类是否已经存在,如果存在了,那么就直接返回,不在创建

虽然使用了一级缓存解决了循环依赖的问题,但要是在多线程下,这个依赖可能就会出现问题.

比如: 有两个线程,同时创建instanceA 和instanceB,instanceA和instanceB都引用了instanceC. 他们同步进行,都去创建instanceC. 首先A去创建,A在实例化instanceC以后就将其放入到一级缓存了,这时候,B去一级缓存里拿. 此时拿到的instanceC是不完整的. 后面的属性赋值,初始化都还没有执行呢. 所以,我们增加二级缓存来解决这个问题. 

 

5. 增加二级缓存,区分完整的bean和纯净的bean.

 MainStart {
    new ConcurrentHashMap<>();

     一级缓存
    etonObjects = ();

     二级缓存
    etonObjects = new ConcurrentHashMap<>();

    *
     * 读取bean定义,1)"> loadBeanDeFinitions(){
        RootBeanDeFinition aBeanDeFinition = );
        beanDeFinitionMap.put(instanceAFinition);
        beanDeFinitionMap.put(instanceBFinition);
    }

            loadBeanDeFinitions();

         第二步: 循环创建bean
         (String key: beanDeFinitionMap.keySet()) {
             第一次: key是instanceA,所以先创建A类
            getBean(key);

        }

         测试: 看是否能执行成功
        InstanceA instanceA = (InstanceA) getBean();
        instanceA.say();

    }

     Object getBean(String beanName) throws Exception {

        // 增加一个出口. 判断实体类是否已经被加载过了
        Object singleton = getSingleton(beanName);
        if (singleton != null) {
            return singleton;
        }

        *
         * 第一步: 实例化
         * 我们这里是模拟,1)"> beanClass.newInstance();
        /**
         * 第二步: 放入到二级缓存
         */
        earlySingletonObjects.put(beanName,instanceBean);

        *
         *  第三步: 属性赋值
         *  instanceA这类类里面有一个属性,1)">*
         * 第四步: 初始化
         * 初始化就是设置类的init-method.这个可以设置也可以不设置. 我们这里就不设置了
         */

        *
         * 第二步: 放入到一级缓存
          instanceBean;
    }

    *
     * 判断是否是循环引用的出口.
     * @param beanName
     * @return
      Object getSingleton(String beanName) {
         先去一级缓存里拿,如果一级缓存没有拿到,去二级缓存里拿
        if (singletonObjects.containsKey(beanName)) {
            return singletonObjects.(beanName);
        } else  (earlySingletonObjects.containsKey(beanName)){
            return earlySingletonObjects.else {
            return null;
        }
    }
}

 

如上图所示,增加了一个二级缓存. 首先,构建出instanceBean以后,直接将其放入到二级缓存中. 这时只是一个纯净的bean,里面还没有给属性赋值,初始化. 在给属性赋值完成,初始化完成以后,在将其放入到一级缓存中. 

我们判断缓存中是否有某个实例bean的时候,先去一级缓存中判断是否有完整的bean,就去二级缓存中判断有没有实例化过这个bean. 

 总结: 一级缓存和二级缓存的作用

 

一级缓存: 解决循环依赖的问题

二级缓存: 在创建实例bean和放入到一级缓存之间还有一段间隙. 如果在这之间从一级缓存拿实例,肯定是返回null的. 为了避免这个问题,增加了二级缓存.

 

我们都知道spring中有一级缓存,二级缓存,三级缓存. 一级缓存和二级缓存的作用我们知道了,那么三级缓存有什么用呢?

 6. 增加三级缓存

 三级缓存有什么作用呢? 这个问题众说纷纭,有说代理,有说AOP. 其实AOP的问题可以用二级缓存来解决. 下面就来看看AOP如何用二级缓存解决.

创建AOP动态代理 (不是耦合的,采用解耦的,通过BeanPostProcessor bean的后置处理器来创建). 之前讲过,如下图

在初始化之后,调用Bean的后置处理器去创建的AOP的动态代理

 

 如上图. 我们在创建bean 的时候,会有很多Bean的后置处理器BeanPostProcessor. 如果有AOP,会在什么时候创建呢? 在初始化以后,调用BeanPostProcessor创建动态代理. 

结合上面的代码,我们想一想,其实在初始化以后创建动态代理就晚了. 为什么呢? 因为,如果有循环依赖,在初始化之后才调用,那就不是动态代理. 其实我们这时候应该在实例化之后,放入到二级缓存之前调用

面试题: 在创建bean的时候,在哪里创建的动态代理,这个应该怎么回答呢?
很多人会说在初始化之后,或者在实例化之后.
其实更严谨的说, 有两种情况: 第一种是在初始化之后调用 . 第二种是出现了循环依赖,会在实例化之后调用

 我们上面说的就是第二种情况. 也就是说,正常情况下是在初始化之后调用的,但是如果有循环依赖,就要在实例化之后调用了.

 

下面来看看如何在二级缓存加动态代理. 

首先,我们这里有循环依赖,所以将动态代理放在实例化之后, 

  /**
         * 第一步: 实例化
         * 我们这里是模拟,1)"> beanClass.newInstance();

        /**
         * 创建AOP动态代理 (不是耦合的,通过BeanPostProcessor bean的后置处理器得来的.  之前讲过,* 在初始化之后,调用Bean的后置处理器去创建的AOP的动态代理 )
         */
        instanceBean = new JdkProxyBeanPostProcessor().getEarlyBeanReference(instanceBean,);

        *
         * 第二步: 放入到二级缓存
         */
        earlySingletonObjects.put(beanName,instanceBean);

        */
      //   正常动态代理创建的时机
        
        *
         * 第五步: 放入到一级缓存
          instanceBean;
    }

 

这里只是简单模拟了动态代理.

我们知道动态代理有两个地方. 如果是普通类动态代理在初始化之后执行,如果是循环依赖,那么动态代理是在实例化之后. 

 

上面在实例化之后创建proxy的代码不完整,为什么不完整呢,因为没有判断是否是循环依赖. 

 

我们简单模拟一个动态代理的实现.

 JdkProxyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
    *
     * 假设A被切点命中 需要创建代理  @pointcut("execution(* *..InstanceA.*(..))")
     * @param bean the raw bean instance
     * @param beanName the name of the bean
     * @return
     * @throws BeansException
     
    @Override
     Object getEarlyBeanReference(Object bean,String beanName) throws BeansException {

         假设A被切点命中 需要创建代理  @pointcut("execution(* *..InstanceA.*(..))")

        /**
         * 这里,我们简单直接判断bean是不是InstanceA实例,如果是,就创建动态代理.
         * 这里没有去解析切点,解析切点是AspectJ做的事.
         */
         (bean instanceof InstanceA) {
            JdkDynimcProxy jdkDynimcProxy = new JdkDynimcProxy(bean);
             jdkDynimcProxy.getProxy();
        }
         bean;
    }
}

 

这里直接判断,如果bean是InstanceA的实例,那么就调用bean的动态代理.  动态代理的简单逻辑就是: 解析切面,然后创建类,如果类不存在就新增,如果存在则不在创建,直接取出来返回.

 

在来看看动态代理,放在实例化之后. 创建AOP,但是,在这里创建AOP动态代理的条件是循环依赖.

问题1: 那么如何判断是循环依赖呢?

二级缓存中bean不是null. 

如果一个类在创建的过程中,会放入到二级缓存,如果完全创建完了,会放入到一级缓存,然后删除二级缓存. 所以,如果二级缓存中的bean只要存在,就说明这个类是创建中,出现了循环依赖.

问题2: 什么时候判断呢?

应该在getSingleton()判断是否是循环依赖的时候判断. 因为这时候我们刚好判断了二级缓存中bean是否为空.

 Object getSingleton(String beanName) {
         (earlySingletonObjects.containsKey(beanName)){

            /**
             * 第一次创建bean是正常的instanceBean. 他并不是循环依赖. 第二次进来判断,这个bean已经存在了,就说明是循环依赖了
             * 这时候通过动态代理创建bean. 然后将这个bean在放入到二级缓存中覆盖原来的instanceBean.
             */
            Object obj =  JdkProxyBeanPostProcessor()
                    .getEarlyBeanReference(earlySingletonObjects.(beanName),beanName);

            earlySingletonObjects.put(beanName,obj);

            ;
        }
    }

 

这样我们在循环依赖的时候就完成了AOP的创建. 这是在二级缓存里创建的AOP,

问题3: 那这是不是说就不需要三级缓存了呢?

那么,来找问题.  这里有两个问题:

问题1: 我们发现在创建动态代理的时候,我们使用的bean的后置处理器JdkProxyBeanPostProcessor.这有点不太符合规则,因为,spring在getBean()的时候并没有使用Bean的后置处理器,而是在createBean()的时候才去使用的bean的后置处理器.
问题2: 如果A是AOP,他一直都是,最开始创建的时候也应该是. 使用这种方法,结果是第一次创建出来的bean不是AOP动态代理.

 

对于第一个问题: 我们希望在实例化的时候创建AOP,但是具体判断是在getSingleton()方法里判断. 这里通过三级缓存来实现. 三级缓存里面放的是一个接口定义的钩子方法. 方法的执行在后面调用的时候执行. 

 

对于第二个问题: 我们的二级缓存就不能直接保存instanceBean实例了,增加一个参数,用来标记当前这个类是一个正在创建中的类. 这样来判断循环依赖.

 

下面先来看看创建的三个缓存和一个标识

 一级缓存
     二级缓存: 为了将成熟的bean和纯净的bean分离. 避免读取到不完整的bean.
    etonObjects = ();

    // 三级缓存:
    private static Map<String,ObjectFactory> singletonFactories = new ConcurrentHashMap<>();

    // 循环依赖的标识---当前正在创建的实例bean
    private static Set<String> singletonsCurrectlyInCreation = new HashSet<>();

 

然后在来看看循环依赖的出口

先去一级缓存里拿
        Object bean = singletonObjects.(beanName);
         一级缓存中没有,但是正在创建的bean标识中有,说明是循环依赖
        if (bean == null && singletonsCurrectlyInCreation.contains(beanName)) {
            bean = earlySingletonObjects.(beanName);
             如果二级缓存中没有,就从三级缓存中拿
             从三级缓存中取
                ObjectFactory objectFactory = singletonFactories.(beanName);
                if (objectFactory != ) {
                     这里是真正创建动态代理的地方.
                    Object obj = objectFactory.getobject();
                     然后将其放入到二级缓存中. 因为如果有多次依赖,就去二级缓存中判断. 已经有了就不在再次创建了
                    earlySingletonObjects.put(beanName,obj);
                }
            }
        }
         bean;
    }

 

这里的逻辑是,先去一级缓存中拿,一级缓存放的是成熟的bean,也就是他已经完成了属性赋值和初始化. 如果一级缓存没有,而正在创建中的类标识是true,就说明这个类正在创建中,这是一个循环依赖. 这个时候就去二级缓存中取数据,二级缓存中的数据是何时放进去的呢,是后面从三级缓存中创建动态代理后放进去的. 如果二级缓存为空,说明没有创建过动态代理,这时候在去三级缓存中拿,然后创建动态代理. 创建完以后放入二级缓存中,后面就不用再创建. 

 

完成的代码如下:

package com.lxl.www.circulardependencies;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowire;
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;

 MainStart {
    ();

     三级缓存:
    etonFactories =  循环依赖的标识---当前正在创建的实例bean
    static Set<String> singletonsCurrectlyInCreation = new HashSet<> main(String[] args) throws Exception {

                loadBeanDeFinitions();

                    getBean(key);

        }

         增加一个出口. 判断实体类是否已经被加载过了
        Object singleton = getSingleton(beanName);
         标记bean正在创建
        if (!singletonsCurrectlyInCreation.contains(beanName)) {
            singletonsCurrectlyInCreation.add(beanName);
        }

        第一步: 实例化
         * 我们这里是模拟,1)"> beanClass.newInstance();


        第二步: 放入到三级缓存
         * 每一次createBean都会将其放入到三级缓存中. getobject是一个钩子方法. 在这里不会被调用.
         * 什么时候被调用呢?
         * 在getSingleton()从三级缓存中取数据,调用创建动态代理的时候
         */
        singletonFactories.put(beanName, ObjectFactory() {
            @Override
             Object getobject() throws BeansException {
                new JdkProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.earlySingletonObjects.put(beanName,instanceBean);

        */


        *
         * 第五步: 放入到一级缓存
         *
         * 在这里二级缓存存的是动态代理,那么一级缓存肯定也要存动态代理的实例.
         * 从二级缓存中取出实例,放入到一级缓存中
         */
         (earlySingletonObjects.containsKey(beanName)) {
            instanceBean = earlySingletonObjects.(beanName);
        }
        singletonObjects.put(beanName,instanceBean);
         instanceBean;
    }

    /**
     * 判断是否是循环引用的出口.
     * @param beanName
     * @return
     */
    先去一级缓存里拿,
        Object bean = singletonObjects.return bean;
    }
}

 

 下面就我们的代码分析一下:

第一种情况: 没有循环依赖

第二种情况: 有循环依赖

第三种情况: 有多次循环依赖

我们模拟一个循环依赖的场景,覆盖这三种情况. 

 

 

 用代码表示

类A

package com.lxl.www.circulardependencies;

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

 A {
    @Autowired
    private B b;

    @Autowired
     C c;
}

类B

 B {
    @Autowired
     A a;

    @Autowired
     B b;
}

类C

 C {
    @Autowired
     A a;
}

其中类A刚好匹配AOP的切面@pointcut("execution(* *..A.*(..))")

 

下面分析他们的循环依赖关系. 

此时beanDeFinitionMap中有三个bean定义. 分别是A,B,C

1. 先解析类A,根据上面的流程.

  1) 首先调用getSingleton,此时一级缓存,二级缓存都没有,正在创建标志也是null. 所以,返回的是null

  2) 标记当前类正在创建中

  3) 实例化

  4) 将A放入到三级缓存,并定义动态代理的钩子方法

  5) 属性赋值. A有两个属性,分别是B和C. 都带有@Autowired注解,先解析B.

  6) A暂停,解析B

2. 解析A类的属性类B

  1) 首先调用getSingleton,返回的是null  

  2) 标记当前类正在创建中

  3) 实例化

  4) 将B放入到三级缓存,并定义动态代理的钩子方法

  5) 属性赋值. B有两个属性,分别是A和C. 都带有@Autowired注解,先解析A. 在解析C

  6) B暂停,解析A

3. 解析B类的属性A 

  1) 首先调用getSingleton,此时一级缓存中这个属性为null,正在创建中标志位true,二级缓存为空,从三级缓存中创建动态代理,然后判断是否符合动态代理切面要求,A符合. 所以通过动态代理创建A的代理bean放入到二级缓存. 返回实例bean.

  2) A此时已经存在了,直接返回

4. 解析B类的属性C

  1) 首先调用getSingleton,返回的是null  

  2) 标记当前类C正在创建中

  3) 实例化

  4) 将C放入到三级缓存,并定义动态代理的钩子方法

  5) 属性赋值. C有一个属性,是A. 带有@Autowired注解,先解析A

  6) C暂停,解析A

5. 解析C中的属性A

  1) 首先调用getSingleton()方法,此时一级缓存中没有,标志位为true,二级缓存中已经有A的动态代理实例了,直接返回.

  2) A此时已经在存在,直接返回

6. 继续解析B类的属性C

  1) 接着第4步往下走

  2) 初始化类C

  3) 将类C放入到一级缓存中. 放之前去二级缓存中取,二级缓存中没有. 所以,这里存的是C通过反射构建的instanceBean

7. 继续解析A类的属性类B

  1) 接着第2步往下走

  2) 初始化类B

  3) 将类B放入到一级缓存中. 放之前去二级缓存中取.二级缓存中没有,这里存的是B通过反射构建的instanceBean

  4) 构建结束,返回

8. 解析A类的属性类C

  1) 首先调用getSingleton()方法,此时一级缓存中已经有了类C,所以直接返回

9. 继续解析A类

  1) 接着第1步往下走

  2) 初始化类A

  3) 将A放入到一级缓存中. 放之前判断二级缓存中有没有实例bean,我们发现有,取出来放入到A的一级缓存中.

  4) 构建bean结束,返回

10. 接下来构建beanDeFinitionMap中的类B

  1) 首先调用getSingleton()方法,此时一级缓存中已经有了类B,所以直接返回

11. 接下来构建beanDeFinitionMap中的类C

  1) 首先调用getSingleton()方法,所以直接返回

 至此整个构建过程结束. 

 

总结: 

再来感受一下三级缓存的作用:

一级缓存: 用来存放成熟的bean. 这个bean如果是切入点,则是一个动态代理的bean,如果不是切入点,则是一个普通的类

二级缓存: 用来存放循环依赖过程中创建的动态代理bean. 

三级缓存: 用来存放动态代理的钩子方法. 用来在需要构建动态代理类的时候使用.

3.2spring源码系列----循环依赖源码分析 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

3.2spring源码系列----循环依赖源码分析 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

首先,我们在3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖 中手写了循环依赖的实现. 这个实现就是模拟的spring的循环依赖. 目的是为了更容易理解spring源码.

下面我们就进入正题,看看spring的循环依赖源码.

 

一、getBean整体流程

 

目标很明确了,就是要看看spring如何解决循环依赖的. 

代码入口是refresh()#finishbeanfactoryInitialization(beanfactory);

二、拆解研究流程中的每一步

调用方法beanfactory.preInstantiateSingletons();实例化剩余的单例bean. 为什么是剩余的?很显然我们在上面已经实例化一部分了.比如配置类,postProcessor等.

2.1 入口

1 @Override
 2     public void preInstantiateSingletons() throws BeansException {
 3         if (logger.isTraceEnabled()) {
 4             logger.trace("Pre-instantiating singletons in " + this);
 5         }
 6 
 7 
 8         // 获取容器中所有bean定义的名字
 9         List<String> beanNames = new ArrayList<>(.beanDeFinitionNames);
10 
11          Trigger initialization of all non-lazy singleton beans...
12         /**
13          * 第一步: 循环bean定义的name
14          */
15         for (String beanName : beanNames) {
16              获取bean定义
17             RootBeanDeFinition bd = getMergedLocalBeanDeFinition(beanName);
18              生产bean定义的条件: 不是抽象的,是单例的,不是懒加载的. 符合这个标准的,最后才会调用getBean()生产bean
19             if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
20                  这里判断是不是工厂bean,这里和beanfactory不是一个意思,判断当前这个bean是否实现了beanfactory的接口
21                  (isfactorybean(beanName)) {
22                     Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
23                      (bean instanceof factorybean) {
24                         final factorybean<?> factory = (factorybean<?>) bean;
25                         boolean isEagerInit;
26                         if (System.getSecurityManager() != null && factory instanceof Smartfactorybean) {
27                             isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
28                                             ((Smartfactorybean<?>) factory)::isEagerInit,29                                     getAccessControlContext());
30                         }
31                         else {
32                             isEagerInit = (factory instanceof Smartfactorybean &&
33                                     ((Smartfactorybean<?>) factory).isEagerInit());
3435                          (isEagerInit) {
36                              获取bean
37                             getBean(beanName);
3839                     }
40                 }
41                  {
              // 第二步: 调用bean定义
42                     getBean(beanName);
4344             }
45         }
46 
47          Trigger post-initialization callback for all applicable beans...
48         
51         52              从缓存中得到实例instance
53             Object singletonInstance = getSingleton(beanName);
54              (singletonInstance instanceof SmartinitializingSingleton) {
55                 final SmartinitializingSingleton smartSingleton = (SmartinitializingSingleton) singletonInstance;
56                 null) {
57                     AccessController.doPrivileged((PrivilegedAction<Object>) () ->58                         smartSingleton.afterSingletonsInstantiated();
59                         return ;
60                     },getAccessControlContext());
6162                 63                     smartSingleton.afterSingletonsInstantiated();
64656667     }

 

首先,循环bean定义,这和我们模拟spring循环的第一步是一样的. 

第二步: 判断从BeanDeFinitionMap中取出来的这个bean是否满足生产bean的条件

我们注意代码注释中, 生产bean定义的条件: 不是抽象的,最后才会调用getBean()生产bean

然后:调用getBean()

到目前为止,我们完成了上图源码图的第一部分:

 

 

 2.2 创建bean前的准备工作

接下来看看getBean().doGetBean()方法

 

1 protected <T> T doGetBean(final String name,@Nullable final Class<T> requiredType,1)">2             @Nullable final Object[] args,boolean typeCheckOnly) throws BeansException {
  3 
  4         // 第一步: 转换bean name. 在这里传入进来的name可能是别名,也有可能是工厂bean的name,所以在这里进行一个转换
  5         final String beanName = transformedBeanName(name);
  6         Object bean;
  7 
   Eagerly check singleton cache for manually registered singletons.
  9         // 第二步: 尝试去缓存中获取对象,如果没有获取到就创建bean
 10         Object sharedInstance = getSingleton(beanName);
 if (sharedInstance != null && args == ) {
 12             13                 判断当前类是否是正在创建中
 14                  (isSingletonCurrentlyInCreation(beanName)) {
 15                     logger.trace(Returning eagerly cached instance of singleton bean '" + beanName +
 16                             ' that is not fully initialized yet - a consequence of a circular reference"17                 }
 18                  {
 19                     logger.trace(Returning cached instance of singleton bean '" + beanName + '2021             }
 22             bean = getobjectForBeanInstance(sharedInstance,name,beanName,2324 
 25         26              Fail if we're already creating this bean instance:
 27              We're assumably within a circular reference.
 28             *
 29              * 判断当前的bean是不是多例,如果是这抛出异常
 30              *
 31              * 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
 32              * spring 只能解决单例对象的setter注入的循环依赖,不能解决构造器注入
 33              *
 34              * 如果是多例的bean,当前正在创建bean,也会抛出异常---这也是循环依赖的问题
 35              */
 36              (isPrototypeCurrentlyInCreation(beanName)) {
 37                 throw new BeanCurrentlyInCreationException(beanName);
 39 
 40             *
 41              * 下面这段代码是关于子父容器的,只有spring mvc继承自spring,才会有子父容器的问题.
 42              43              Check if bean deFinition exists in this factory.
 44             beanfactory parentbeanfactory = getParentbeanfactory();
 45             if (parentbeanfactory != null && !containsBeanDeFinition(beanName)) {
 46                  Not found -> check parent.
 47                 String nametoLookup = originalBeanName(name);
 48                  (parentbeanfactory instanceof Abstractbeanfactory) {
 49                     return ((Abstractbeanfactory) parentbeanfactory).doGetBean(
 50                             nametoLookup,requiredType,args,typeCheckOnly);
 5152                 else if (args != 53                      Delegation to parent with explicit args.
 54                      (T) parentbeanfactory.getBean(nametoLookup,args);
 55if (requiredType != 57                      No args -> delegate to standard getBean method.
 58                      parentbeanfactory.getBean(nametoLookup,requiredType);
 5960                 61                      (T) parentbeanfactory.getBean(nametoLookup);
 6264 
 65             *
 66              * 方法参数typeCheckOnly是用来判断#getBean()方法时,表示是否为仅仅进行类型检查,67              * 如果不仅仅做类型检查,而是创建bean对象,则需要调用#markBeanAsCreated(String name)
 68              *
 69              70             if (!typeCheckOnly) {
 71                 markBeanAsCreated(beanName);
 7273 
 74             try75                 final RootBeanDeFinition mbd = getMergedLocalBeanDeFinition(beanName);
 76                 checkMergedBeanDeFinition(mbd,1)">77 
 78                  Guarantee initialization of beans that the current bean depends on.
 79                 *
 80                  * 现在有两个bean1,bean2,加载的时候调用的是bean1,bean2. 但如果我们想要bean2优先加载,就使用@DependOn注解
 81                  * 用来解析带有dependOn注解的类
 82                  83                 String[] dependsOn = mbd.getDependsOn();
 84                 if (dependsOn != 85                      (String dep : dependsOn) {
 86                          (isDependent(beanName,dep)) {
 87                              BeanCreationException(mbd.getResourceDescription(),1)">88                                     Circular depends-on relationship between '' and '" + dep + 89                         }
 90                         registerDependentBean(dep,beanName);
 91                         92                             getBean(dep);
 9394                         catch (NoSuchBeanDeFinitionException ex) {
 95                             96                                     ' depends on missing bean ',ex);
 9798                     }
 99100 
101                  Create bean instance.
102                 *
103                  * 第三步: 创建单例bean实例
104                  105                 if (mbd.isSingleton()) {  处理单例bean
106                     *
107                      * 这里getSingleton()和上面的getSigleton不一样,上面的是从一级缓存中拿.
108                      * 这个getSingleton()就办了一件事: 将bean设置为正在创建的状态. 这个状态很重要,如果出现循环依赖,发现bean正在创建,就不会再创建了
109                      110                     sharedInstance = getSingleton(beanName,() ->111                         112                              createBean(beanName,mbd,args);
113114                          (BeansException ex) {
115                              Explicitly remove instance from singleton cache: It might have been put there
116                              eagerly by the creation process,to allow for circular reference resolution.
117                              Also remove any beans that received a temporary reference to the bean.
118                             destroySingleton(beanName);
119                             throw ex;
120121                     });
122                      得到bean实例对象
123                     bean = getobjectForBeanInstance(sharedInstance,mbd);
124125 
126                 if (mbd.isPrototype()) {  处理多例bean
127                      It's a prototype -> create a new instance.
128                     Object prototypeInstance = 129                     130                          当前正在创建多例bean
131                         beforePrototypeCreation(beanName);
132                          执行创建bean
133                         prototypeInstance =134135                     finally136                         afterPrototypeCreation(beanName);
137138                      获取bean实例对象
139                     bean = getobjectForBeanInstance(prototypeInstance,1)">140141 
142                 else {  处理其他类型的bean
143                     String scopeName = mbd.getScope();
144                     final Scope scope = this.scopes.get(scopeName);
145                     if (scope == 146                         new IllegalStateException(No Scope registered for scope name '" + scopeName + );
147148                     149                         Object scopedInstance = scope.get(beanName,1)">150                             beforePrototypeCreation(beanName);
151                             152                                 153                             }
154                             155                                 afterPrototypeCreation(beanName);
156157                         });
158                         bean = getobjectForBeanInstance(scopedInstance,1)">159160                      (IllegalStateException ex) {
161                          BeanCreationException(beanName,1)">162                                 Scope '' is not active for the current thread; consider " +
163                                 defining a scoped proxy for this bean if you intend to refer to it from a singleton164                                 ex);
165166167168             169                 cleanupAfterBeanCreationFailure(beanName);
170                 171172         } 

 

在这里,首先从缓存中获取bean,看缓存中是否已经存在了

 Object sharedInstance = getSingleton(beanName);

然后,如果缓存中已经存在了,那么久直接取出来. 代码如下: 

    if (sharedInstance != null && args == null) {
             (logger.isTraceEnabled()) {
                判断当前bean是否是正在创建中(单例bean)
                 (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace(" + beanName +
                            );
                }
                 {
                    logger.trace();
                }
            }
            bean = getobjectForBeanInstance(sharedInstance,null);
        }

 

如果是空,就说明是第一次创建,执行else的部分

首先,判断是否是正在创建的多例bean,如果是正在创建的多例bean,就抛出异常,

  已经是正在创建了,说明这至少是第二次了,这里处理的是单例bean的循环依赖,不处理多例bean的循环依赖,所以抛出异常

  对应的代码是这一句

  

*
 29              * 判断当前的bean是不是多例,如果是这抛出异常
 30              *
 31              * 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
 32              * spring 只能解决单例对象的setter注入的循环依赖,1)">38             }

那么,接下来就是首次创建bean. 首次创建的bean有三种情况:

  第一种,这个bean是单例的.

  第二种,这个bean是多例的.

  第三种. 其他类型

对应的代码就是这一块. 有行号,可以和上面一一对应上

if (mbd.isSingleton()) {  处理单例bean
mbd.isPrototype()) {  处理多例bean
else {  处理其他类型的bean
166                 }

 

我们的重点研究对象是单例bean. 所以,重点看单例bean的实现

if (mbd.isSingleton()) { // 处理单例bean
110                     sharedInstance = getSingleton(beanName,() -> {
111                         try {
112                             return createBean(beanName,args);
113                         }
114                         catch (BeansException ex) {
115                             // Explicitly remove instance from singleton cache: It might have been put there
116                             // eagerly by the creation process,to allow for circular reference resolution.
117                             // Also remove any beans that received a temporary reference to the bean.
118                             destroySingleton(beanName);
119                             throw ex;
120                         }
                     });
123                     bean =124                 }

 

这里的重点是调用了getSingleton(beanName,FactoryObject); FactoryObject是一个接口. 定义了一个钩子方法getobject(). 

这个接口在这里这是进行了定义,并不会执行. 什么时候执行呢? 后面调用的时候执行. 

下面来看看getSingleton()方法,钩子方法也是在这里被调用的.

 public Object getSingleton(String beanName,ObjectFactory<?> singletonFactory) {
 2         Assert.notNull(beanName,Bean name must not be null3         synchronized (.singletonObjects) {
 4             // 第一步: 从一级缓存中获取单例对象
 5             Object singletonObject = this.singletonObjects.(beanName);
 6             if (singletonObject == 7                 .singletonsCurrentlyInDestruction) {
 8                      BeanCreationNotAllowedException(beanName,1)">9                             Singleton bean creation not allowed while singletons of this factory are in destruction 10                             (Do not request a bean from a beanfactory in a destroy method implementation!)1112                  (logger.isDebugEnabled()) {
13                     logger.debug(Creating shared instance of singleton bean '1415                 // 第二步: 将bean添加到singletonsCurrentlyInCreation中,表示bean正在创建
16                 beforeSingletonCreation(beanName);
17                 boolean newSingleton = false18                 boolean recordSuppressedExceptions = (this.suppressedExceptions == 19                  (recordSuppressedExceptions) {
20                     this.suppressedExceptions = new LinkedHashSet<>();
22                 23                     // 第三步: 这里调用getobject()钩子方法,就会回调匿名函数,调用singletonFactory的createBean()
24                     singletonObject = singletonFactory.getobject();
25                     newSingleton = true2627                 28                      Has the singleton object implicitly appeared in the meantime ->
29                      if yes,proceed with it since the exception indicates that state.
30                     singletonObject = (beanName);
31                     32                         3335                  (BeanCreationException ex) {
36                     37                         for (Exception suppressedException : .suppressedExceptions) {
                             ex.addRelatedCause(suppressedException);
41                     43                 44                     45                         4647                     afterSingletonCreation(beanName);
4849                  (newSingleton) {
                     addSingleton(beanName,singletonObject);
5253              singletonObject;
5455     }

 

这里是调用getBean().

第一步: 去一级缓存中取成熟的单例bean. 如果拿到了,就直接返回. 如果没拿到. 那么执行创建. 

第二步: 在创建之前,先把这个bean放入到正在创建的单例bean集合中. 标记这个bean正在创建中

第三步: 就是调用钩子方法getobject()了. 这个方法的方法体是在上面定义的. 其内容是去创建实例

            sharedInstance = getSingleton(beanName,1)"> {
                         {
                            // 这里定义了一个钩子函数. 此时只是定义,并不执行. 在真正需要创建bean的地方才会执行
                            return createBean(beanName,args);
                        }
                         (BeansException ex) {
                             Explicitly remove instance from singleton cache: It might have been put there
                            cular reference resolution.
                             Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                             ex;
                        }
                    });

 

这里的代码逻辑是完成了创建之前的逻辑

2.3 创建bean 

下面看看创建bean的过程

  1 protected Object doCreateBean(final String beanName,final RootBeanDeFinition mbd,final @Nullable Object[] args)
  2             throws BeanCreationException {
  3 
  4          Instantiate the bean.
  5         BeanWrapper instanceWrapper = ;
  6          (mbd.isSingleton()) {
  7             instanceWrapper = .factorybeanInstanceCache.remove(beanName);
  8         }
  9         if (instanceWrapper == ) {
 10             *
 11              * 第一步: 实例化
 12              * 这里面的调用链非常深,后面再看
 13              * bean实例化有两种方式
 14              * 1. 使用反射:  使用反射也有两种方式, 15              *         a. 通过无参构造函数 (默认的方式)
 16              *             从beanDeFinition中可以得到beanClass,1)"> 17              *             ClassName = BeanDeFinition.beanClass
 18              *             Class clazz = Class.forName(ClassName);
 19              *             clazz.newInstance();
 20              *             这样就可以实例化bean了
 21              *
 22              *         b. 通过有参函数.
 23              *            ClassName = BeanDeFinition.beanClass
 24  25              *             Constractor con = class.getConstractor(args....)
 26              *             con.newInstance();
 27  28              * 2. 使用工厂
 29              *         我们使用@Bean的方式,就是使用的工厂模式,自己控制实例化过程
 30  31              */
 32             instanceWrapper = createBeanInstance(beanName,args);
 33  34          这里使用了装饰器的设计模式
 35         final Object bean = instanceWrapper.getWrappedInstance();
 36         Class<?> beanType = instanceWrapper.getWrappedClass();
 37         if (beanType != NullBean.class 38             mbd.resolvedtargettype = beanType;
 39  40 
 41          Allow post-processors to modify the merged bean deFinition.
 42          允许后置处理器修改已经合并的beanDeFinition
 43         synchronized (mbd.postProcessingLock) {
 44             mbd.postProcessed) {
 45                  {
 46                     applyMergedBeanDeFinitionPostProcessors(mbd,beanType,beanName);
 47                 }
 48                  (Throwable ex) {
 49                      50                             Post-processing of merged bean deFinition Failed 51  52                 mbd.postProcessed =  53             }
 54  55 
 56          57          * 缓存单例bean到三级缓存中,以防止循环依赖
 58          * 判断是否是早期引用的bean,如果是,则允许提前暴露引用
 59      *
 60          * 判断是否能够早起暴露的条件
 61          *     1. 是单例
 62          *     2. 允许循环依赖
 63          *     3. 正在创建的bean
 64           65         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 66                 isSingletonCurrentlyInCreation(beanName));
 67          (earlySingletonExposure) {
 68              (logger.isTraceEnabled()) {
 69                 logger.trace(Eagerly caching bean '" + beanName +
 70                         ' to allow for resolving potential circular references);
 71  72              把我们的早期对象包装成一个singletonFactory对象,该对象提供了getobject()方法,把静态的bean放到三级缓存中去了.
 73             addSingletonFactory(beanName,1)"> getEarlyBeanReference(beanName,bean));
 74  75 
 76          Initialize the bean instance.
 77         Object exposedobject = bean;
 78          79              第二步:填充属性,给属性赋值(调用set方法)  这里也是调用的后置处理器
 80             populateBean(beanName,instanceWrapper);
 81             // 第三步: 初始化.
 82             exposedobject = initializeBean(beanName,exposedobject,mbd);
 83  84          85             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 86                  (BeanCreationException) ex;
 87  88              89                  BeanCreationException(
 90                         mbd.getResourceDescription(),1)">Initialization of bean Failed 91  92  93 
 94          95          * 初始化完成以后,判断是否是早期的对象
 96          * 是循环依赖. 才会走进这里来
 97            98          99              去缓存中获取到我们的对象 由于传递的allowEarlyReference是false,要求只能在一级二级缓存中取
100              正常的普通的bean(不存在循环依赖的bean) 创建的过程中,不会把三级缓存提升到二级缓存中.
101             Object earlySingletonReference = getSingleton(beanName,1)">102             if (earlySingletonReference != 103                 if (exposedobject == bean) {
104                     exposedobject = earlySingletonReference;
105 106                 this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
107                     String[] dependentBeans = getDependentBeans(beanName);
108                     Set<String> actualDependentBeans = (dependentBeans.length);
109                      (String dependentBean : dependentBeans) {
110                         removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
111                             actualDependentBeans.add(dependentBean);
112                         }
113                     }
114                     actualDependentBeans.isEmpty()) {
115                          BeanCurrentlyInCreationException(beanName,1)">116                                 Bean with name '' has been injected into other beans [" +
117                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
118                                 ] in its raw version as part of a circular reference,but has eventually been 119                                 wrapped. This means that said other beans do not use the final version of the 120                                 bean. This is often the result of over-eager type matching - consider using 121                                 'getBeanNamesForType' with the 'allowEagerInit' flag turned off,for example.122 123 124 125 126 
127          Register bean as disposable.
128         129             registerdisposableBeanIfNecessary(beanName,bean,1)">130 131          (BeanDeFinitionValidationException ex) {
132             133                     mbd.getResourceDescription(),1)">Invalid destruction signature134 135 
136          exposedobject;
137     }

 

首先,实例化bean,实例化的方式有两种. 一种是通过反射,另一种是通过动态

 1         2  3  4  5              * 1. 使用反射:  使用反射也有两种方式,1)"> 6  7  8  9 10 11 12 13 14 15 16 17 18 19              * 2. 使用工厂
20 21 22              23             instanceWrapper = createBeanInstance(beanName,args);

 

判断是否是早期暴露的bean. 满足早期暴露的bean的三个条件是

1. 是单例的

2. 允许循环依赖

3. bean已经是处在正在创建中的行列了.

      判断是否能够早起暴露的条件
         *     1. 是单例
         *     2. 允许循环依赖
         *     3. 正在创建的bean
         */
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));    

 

创建bean的第二步: 属性赋值

// 第二步:填充属性,给属性赋值(调用set方法)  这里也是调用的后置处理器
populateBean(beanName,instanceWrapper);

在这里会判断,是否带有@Autowired的属性. 分为两种一种是Name,一种是Type

@SuppressWarnings(deprecation")   for postProcesspropertyValues
    protected  populateBean(String beanName,RootBeanDeFinition mbd,@Nullable BeanWrapper bw) {
        if (bw == ) {
             (mbd.hasPropertyValues()) {
                 BeanCreationException(
                        mbd.getResourceDescription(),1)">Cannot apply property values to null instance);
            }
             {
                 Skip property population phase for null instance.
                ;
            }
        }

         Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
         state of the bean before properties are set. This can be used,for example,1)"> to support styles of field injection.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
             (BeanPostProcessor bp : getBeanPostProcessors()) {
                 (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    ibp.postProcessAfterInstantiation(bw.getWrappedInstance(),beanName)) {
                        ;
                    }
                }
            }
        }

        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : );

         判断属性是否有Autowired注解
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
         Autowired是根据名字或者根据类型
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName,bw,newPvs);
            }
            // Add property values based on autowire by type if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName,newPvs);
            }
            pvs = newPvs;
        }

        ......
    }

 

如果按照名字注入

 1  autowireByName(
            String beanName,AbstractBeanDeFinition mbd,BeanWrapper bw,MutablePropertyValues pvs) {
 3 
 4         String[] propertyNames = unsatisfiednonSimpleProperties(mbd,bw);
 5          (String propertyName : propertyNames) {
 6              (containsBean(propertyName)) {
 7                 // 调用getBean
 8                 Object bean = getBean(propertyName);
                pvs.add(propertyName,bean);
                registerDependentBean(propertyName,1)">11                 12                     logger.trace(Added autowiring by name from bean name '13                             ' via property '" + propertyName + ' to bean named '17                 18                     logger.trace(Not autowiring property '' of bean '19                             ' by name: no matching bean found22 23     }

 

会再次调用getBean方法. 构建bean. 这是就有可能出现循环依赖了. 

按类型注入也是一样的. 

只是解析bean的方式不同.

 

创建bean的第三步: 初始化

 // 第三步: 初始化.
 exposedobject = initializeBean(beanName,mbd);

在初始化bean的时候,会调用很多的aware. 还会调用init-method方法. 以及bean的后置处理器.

 

第四步:删除实例化和静态方法在缓存中的数据

*
         * 初始化完成以后,判断是否是早期的对象
         * 是循环依赖. 才会走进这里来
          */
         (earlySingletonExposure) {
            
            Object earlySingletonReference = getSingleton(beanName,1)">);
            ) {
                 bean) {
                    exposedobject = earlySingletonReference;
                }
                 hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = (dependentBeans.length);
                     (String dependentBean : dependentBeans) {
                        removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    actualDependentBeans.isEmpty()) {
                        " +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                " +
                                );
                    }
                }
            }
        }

 

removeSingletonIfCreatedForTypeCheckOnly调用方法,删除缓存.

这既是getBean()整个的过程. 中间还有很多细节,没有往里面深入的看,因为spring代码非常的深,看的太深就忘了我们的目标了. 结合之前手写的spring循环依赖的思想看,还是可以看得懂的. 

 

 

三. 接下来有几个问题

问题1: 为什么需要二级缓存和三级缓存?

一级缓存: 用来存储完整的bean

二级缓存: 用来存储早期的,纯净的bean,也就是没有注入属性的bean

三级缓存: 存的是函数的接口,主要目的是为了解耦

 二级缓存 和三级缓存 结合起来,解决了循环依赖下的AOP动态代理的问题

问题2:有没有解决构造函数的循环依赖

答案是没有. 因为构造函数是在实例化的时候构建的. 这个时候bean都还没有创建,所以没有办法处理循环依赖.如果出现构造函数的循环依赖,是会直接报错的..

 

问题3:有没有解决多例下的循环依赖

也是没有的,因为我们会判断,如果是多例,那么会抛出异常

 1             /**
 2              * 第二步: 判断当前bean是否是正在创建中的多例bean,如果是就抛出异常
 3              *
 4              * 2. 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
 5              * spring 只能解决单例对象的setter注入的循环依赖,不能解决构造器注入
 6              *
 7              * 如果是多例的bean,也会抛出异常---这也是循环依赖的问题
 8              */
 9              (isPrototypeCurrentlyInCreation(beanName)) {
10                  BeanCurrentlyInCreationException(beanName);
11             }   

 

3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析

3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析

根据之前解析的循环依赖的源码,分析了一级缓存,二级缓存,三级缓存的作用以及如何解决循环依赖的. 然而在多线程的情况下,Spring在创建bean的过程中,可能会读取到不完整的bean. 下面,我们就来研究两点:

1. 为什么会读取到不完整的bean.

2. 如何解决读取到不完整bean的问题.

 

和本文相关的spring循环依赖的前两篇博文如下: 

3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

3.2spring源码系列----循环依赖源码分析

一. 为什么会读取到不完整的bean.

我们知道,如果spring容器已经加载完了,那么肯定所有bean都是完整的了,但如果,spring没有加载完,在加载的过程中,构建bean就有可能出现不完整bean的情况

如下所示: 

首先,有一个线程要去创建A类,调用getBean(A),他会怎么做呢?

第一步: 调用getSingleton()方法,去缓存中取数据,我们发现缓存中啥都没有,肯定返回null. 

第二步: 将其放入到正在创建集合中,标记当前bean A正在创建

第三步: 实例化bean

第四步: 将bean放到三级缓存中. 定义一个函数接口,方便后面调用

addSingletonFactory(beanName,() -> getEarlyBeanReference(beanName,mbd,bean));

第四步: 属性赋值. 在属性赋值的时候,返现要加载类B,就在这个时候,另一个线程也进来了,要创建Bean A.

第五步: 线程2 创建bean,也是先去调用getSinglton()从缓存中取,一二级换粗中都没有,但是三级缓存中却是有的. 于是就调用动态代理,去创建bean,很显然这时候创建的bean是不完整的. 然后将其放入到二级缓存中,二级缓存里的bean也是不完整的. 这就导致了后面是用的bean可能都是不完整的. 详细的分析上图

 

二. 如何解决读取到不完整bean的问题.

其实,之所以出现这样的问题,原因就在于,第一个bean还没有被创建完,第二个bean就开始了. 这是典型的并发问题. 

针对这个问题,其实,我们加锁就可以了.  

 用自己手写的代码为例

第一: 将整个创建过程加一把锁

/**
     * 获取bean,根据beanName获取
     */
    public static Object getBean(String beanName) throws Exception {

        // 增加一个出口. 判断实体类是否已经被加载过了
        Object singleton = getSingleton(beanName);
        if (singleton != null) {
            return singleton;
        }
        Object instanceBean;
        synchronized (singletonObjects) {

             标记bean正在创建
            if (!singletonsCurrectlyInCreation.contains(beanName)) {
                singletonsCurrectlyInCreation.add(beanName);
            }

            *
             * 第一步: 实例化
             * 我们这里是模拟,采用反射的方式进行实例化. 调用的也是最简单的无参构造函数
             */
            RootBeanDeFinition beanDeFinition = (RootBeanDeFinition) beanDeFinitionMap.get(beanName);
            Class<?> beanClass = beanDeFinition.getBeanClass();
             调用无参的构造函数进行实例化
            instanceBean = beanClass.newInstance();


            *
             * 第二步: 放入到三级缓存
             * 每一次createBean都会将其放入到三级缓存中. getobject是一个钩子方法. 在这里不会被调用.
             * 什么时候被调用呢?
             * 在getSingleton()从三级缓存中取数据,调用创建动态代理的时候
             
            singletonFactories.put(beanName,new ObjectFactory() {
                @Override
                public Object getobject() throws BeansException {
                    return new JdkProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.(beanName),beanName);
                }
            });
            earlySingletonObjects.put(beanName,instanceBean);

            *
             *  第三步: 属性赋值
             *  instanceA这类类里面有一个属性,InstanceB. 所以,先拿到 instanceB,然后在判断属性头上有没有Autowired注解.
             *  注意: 这里我们只是判断有没有Autowired注解. spring中还会判断有没有@Resource注解. @Resource注解还有两种方式,一种是name,一种是type
             
            Field[] declaredFields = beanClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                 判断每一个属性是否有@Autowired注解
                Autowired annotation = declaredField.getAnnotation(Autowired.class);
                if (annotation != ) {
                     设置这个属性是可访问的
                    declaredField.setAccessible(true);
                     那么这个时候还要构建这个属性的bean.
                    
                     * 获取属性的名字
                     * 真实情况,spring这里会判断,是根据名字,还是类型,还是构造函数来获取类.
                     * 我们这里模拟,所以简单一些,直接根据名字获取.
                     
                    String name = declaredField.getName();

                    *
                     * 这样,在这里我们就拿到了 instanceB 的 bean
                     
                    Object fileObject = getBean(name);

                     为属性设置类型
                    declaredField.set(instanceBean,fileObject);
                }
            }


            *
             * 第四步: 初始化
             * 初始化就是设置类的init-method.这个可以设置也可以不设置. 我们这里就不设置了
             */


            *
             * 第五步: 放入到一级缓存
             *
             * 在这里二级缓存存的是动态代理,那么一级缓存肯定也要存动态代理的实例.
             * 从二级缓存中取出实例,放入到一级缓存中
             */
            if (earlySingletonObjects.containsKey(beanName)) {
                instanceBean = earlySingletonObjects.(beanName);
            }
            singletonObjects.put(beanName,instanceBean);

             删除二级缓存

             删除三级缓存
        }
         instanceBean;
    }

 

然后在从缓存取数据的getSingleton()上也加一把锁

private  Object getSingleton(String beanName) {
        先去一级缓存里拿,
        Object bean = singletonObjects.(beanName);
         一级缓存中没有,但是正在创建的bean标识中有,说明是循环依赖
        if (bean == null && singletonsCurrectlyInCreation.contains(beanName)) {
            synchronized (singletonObjects) {
                bean = earlySingletonObjects.(beanName);
                 如果二级缓存中没有,就从三级缓存中拿
                 从三级缓存中取
                    ObjectFactory objectFactory = singletonFactories.(beanName);
                    if (objectFactory != ) {
                         这里是真正创建动态代理的地方.
                        bean = objectFactory.getobject();
                         然后将其放入到二级缓存中. 因为如果有多次依赖,就去二级缓存中判断. 已经有了就不在再次创建了
                        earlySingletonObjects.put(beanName,bean);
                    }
                }
            }
        }
         bean;
    }

加了两把锁.

 

这样,在分析一下

 

如上图,线程B执行到getSingleton()的时候,从一级缓存中取没有,到二级缓存的时候就加锁了,他要等待直到线程A完成执行完才能进入. 这样就避免出现不完整bean的情况. 

 

三. 源码解决

在创建实例bean的时候,加了一把锁,锁是一级缓存.

 1 public Object getSingleton(String beanName,ObjectFactory<?> singletonFactory) {
 2         Assert.notNull(beanName,"Bean name must not be null");
 3         synchronized (this.singletonObjects) {
 4              第一步: 从一级缓存中获取单例对象
 5             Object singletonObject = this.singletonObjects.(beanName);
 6             if (singletonObject == ) {
 7                 if (this.singletonsCurrentlyInDestruction) {
 8                     throw  BeanCreationNotAllowedException(beanName,9                             Singleton bean creation not allowed while singletons of this factory are in destruction " +
10                             (Do not request a bean from a beanfactory in a destroy method implementation!));
11                 }
12                  (logger.isDebugEnabled()) {
13                     logger.debug(Creating shared instance of singleton bean '" + beanName + '1415                  第二步: 将bean添加到singletonsCurrentlyInCreation中,表示bean正在创建
16                 beforeSingletonCreation(beanName);
17                 boolean newSingleton = false;
18                 boolean recordSuppressedExceptions = (this.suppressedExceptions == 19                  (recordSuppressedExceptions) {
20                     this.suppressedExceptions = new LinkedHashSet<>();
2122                 try {
23                      第三步: 这里调用getobject()钩子方法,就会回调匿名函数,调用singletonFactory的createBean()
24                     singletonObject = singletonFactory.getobject();
25                     newSingleton = 2627                 catch (IllegalStateException ex) {
28                      Has the singleton object implicitly appeared in the meantime ->
29                      if yes,proceed with it since the exception indicates that state.
30                     singletonObject = (beanName);
31                     ) {
32                         throw ex;
33                     }
3435                  (BeanCreationException ex) {
36                     37                         for (Exception suppressedException : .suppressedExceptions) {
38                             ex.addRelatedCause(suppressedException);
39                         }
4041                     4243                 finally44                     45                         4647                     afterSingletonCreation(beanName);
4849                  (newSingleton) {
50                     addSingleton(beanName,singletonObject);
5152             }
53              singletonObject;
54         }
55     }

 

再从缓存中取数据的时候,也加了一把锁,和我们的demo逻辑是一样的. 锁也是一级缓存.

protected Object getSingleton(String beanName,boolean allowEarlyReference) {
         从一级缓存中获取bean实例对象
        Object singletonObject = *
         * 如果在第一级的缓存中没有获取到对象,并且singletonsCurrentlyIncreation为true,也就是这个类正在创建.
         * 标明当前是一个循环依赖.
         *
         * 这里有处理循环依赖的问题.-- 我们使用三级缓存解决循环依赖
         */
         isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                *
                 * 从二级缓存中拿bean,二级缓存中的对象是一个早期对象
                 * 什么是早期对象?就是bean刚刚调用了构造方法,还没有给bean的属性进行赋值,和初始化,这就是早期对象
                  

                singletonObject = this.earlySingletonObjects. allowEarlyReference) {
                    *
                     * 从三级缓存拿bean,singletonFactories是用来解决循环依赖的关键所在.
                     * 在ios后期的过程中,当bean调用了构造方法的时候,把早期对象包装成一个ObjectFactory对象,暴露在三级缓存中
                      
                    ObjectFactory<?> singletonFactory = this.singletonFactories.if (singletonFactory != *
                         * 在这里通过暴露的ObjectFactory包装对象. 通过调用他的getobject()方法来获取对象
                         * 在这个环节中会调用getEarlyBeanReference()来进行后置处理
                         
                        singletonObject = singletonFactory.getobject();
                         把早期对象放置在二级缓存中
                        .earlySingletonObjects.put(beanName,singletonObject);
                         删除三级缓存
                        .singletonFactories.remove(beanName);
                    }
                }
            }
         singletonObject;
    }

 

关于Spring5 依赖注入和循环依赖处理spring依赖注入原理的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于.net – 依赖注入解决循环依赖关系、3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖、3.2spring源码系列----循环依赖源码分析 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖、3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析的相关信息,请在本站寻找。

本文标签: