Spring循环依赖解决

循环依赖终极讲解

课程内容

  • 为什么要二级缓存和三级缓存
    • 没有循环依赖不会访问二三级缓存的
    • 二级缓存:将纯净的bean和成熟的bean做分离
    • 二级缓存+两把锁解决多线程下获取到不完整的bean的问题
    • 三级缓存:三级缓存的是函数式接口,调用我们的bean的后置处理器这里面会做实现AOP,主要用来做解耦
    • Aop也可以二级缓存来解决
    • 二级缓存+三级缓存:循环依赖下AOP的动态代理的问题
  • Spring有没有解决构造函数的循环依赖
    • 没有,因为构造函数在实例化当中,连实例都拿不到不能解决循环依赖;如果存在构造函数的循环依赖,会直接报错的
  • Spring有没有解决多例下的循环依赖
    • 多例bean不会存到缓存中,自然不会解决循环依赖
    • 解决循环依赖的关键就是三级缓存,而三级缓存还解决了保证单例唯一性的问题。因为从缓存中取出来的实例是要保证bean是唯一的,所以三级缓存支持不了prototype。这也是prototype没有使用三级缓存而是简单的将bean的名字放到缓存当中的原因
  • Spring读取不完整Bean的最终解决原理:Spring容器已经加载完之后,getbean时肯定是一个完整的bean,读取到不完整的bean的问题一定是Spring容器正在创建bean的过程当中,多个线程进来getBean所读取到的不完整的bean
    • 二级缓存还是不能完整的解决Spring正在创建过程当中所出现的多线程读取到不完整的bean的
      • 线程1: getBean(A)->getSingleton(A),返回null ->添加到正在创建集合中->实例化->存到三级缓存中->解析属性->发现A中依赖B->getBean(B).线程A停在这里
      • 线程2: getBean(A)->getSingleton(A),一级缓存中仍然没有,但此时beanA已经标记为正在创建,在getSingleton()方法中会从二级缓存中拿(只有调用了三级缓存,才会去创建AOP实例或者拿到本身的实例,再存到二级缓存),此时二级缓存中仍然没有,从三级缓存中取,此时三级缓存中的beanA还没有解析完beanB
    • 通过线程1和线程2可以得知仍然不能解决读取到不完整的bean的问题,要想解决这个问题就需要加两把锁
    • 加锁之后的分析
      • 线程1: getBean(A)->getSingleton(A),返回null ->加锁,添加到正在创建集合中->实例化->存到三级缓存中->解析属性->发现A中依赖B->getBean(B).线程A停在这里,仍在锁当中,线程A继续执行直到释放锁,线程B才能继续执行
      • 线程2: getBean(A)->getSingleton(A),一级缓存中仍然没有,但此时beanA已经标记为正在创建->加锁,阻塞在这里
    • DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)对一级缓存加了锁,直接锁住了整个创建过程
    • DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference)对一级缓存加了锁

创建bean时在哪里创建了动态代理:初始化之后或者出现了循环依赖,实例化之后创建动态代理

为初始化对象创建动态代理,将这个代理对象放到二级缓存里面

正常情况下(正常的bean)会在初始化之后创建动态代理

只在循环依赖的情况下在实例化后创建动态代理:如何判断当前是不是循环依赖:singletonsCurrentlyInCreation集合

#DefaultListableBeanFactory
@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		//获取我们容器中所有bean定义的名称
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// 循环我们所有的bean定义名称
		for (String beanName : beanNames) {
			//合并我们得bean定义,转换为统一的RootBeanDefinition类型,方便后续处理
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//根据bean定义判断是不是抽象的&&不是单例的&&不是懒加载的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							//调用真正的getBean的流程
							getBean(beanName);
						}
					}
				}
				else {
					//非工厂bean.就是普通的bean
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}
	
	
	
@Override
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}



protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		
    	//在这里传入的name可能是别名,也有可能是工厂bean的name,所以需要在这里转换
		final String beanName = transformedBeanName(name);
		Object bean;

    	//尝试去缓冲中获取对象
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
            //如果sharedInstance是普通的单例bean,下面的方法会直接返回,但如果sharedInstance是Factory类型的bean,则需要调用getObject工厂方法获取真正的bean实例.如果用户想获取FactoryBean本身,这里也不会做特别的处理,直接返回即可.毕竟FactoryBean的实现类本身也是一种bean,只不过具有特殊的功能而已.
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			//spring只能解决单例对象的setter注入的循环以来,不能解决构造器注入
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
            //若存在父工厂且当前的bean工厂不存在当前的bean定义,那么bean定义一定是存在父beanFactory
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				//获取bean的原始名称
				String nameToLookup = originalBeanName(name);
                //若为AbstractBeanFactory类型,委托父类处理
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// 委托给构造函数getBean()处理
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					//没有args,委托给标准的getBean()处理
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}
			//方法参数typeCheckOnly,是用来判断调用#getBean(...)方法时,标识是否为仅仅进行类型检查
            //如果不是仅仅做类型检查,而是创建Bean对象,则需要调用#markBeanAsCreated(beanName)
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				//处理dependsOn的依赖(这个不是我们的所谓的循环依赖,而是bean创建前后的依赖)
				// 依赖bean的名称
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
                    //若给定的依赖Bean已经注册为依赖给定的bean,及循环依赖的情况:抛出BeanCreationException异常
					for (String dep : dependsOn) {
                        //beanName是当前正在创建的bean,dep是正在创建的bean的依赖的bean的名称
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
                        //保存的是beanName之间的映射关系:依赖beanName->dep的集合
						registerDependentBean(dep, beanName);
						try {
                            //获取dependsOn的bean,优先加载这个bean
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// 创建单例bean
				if (mbd.isSingleton()) {
                    //如果beanName和一个singletonFactory传入一个回调对象用于回调
                    //在#getSingleton()方法中会将当前bean标记为正在创建
					sharedInstance = getSingleton(beanName, () -> {
						try {
                            //进入创建bean的逻辑
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}



@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //第一步:我们尝试去一级缓存(单例缓存池中去获取对象,一般情况下从该map获取的对象是直接可以使用的)
        //IOC容器中初始化加载单实例bean的时候第一次进来的时候,该map一般返回空
		Object singletonObject = this.singletonObjects.get(beanName);
        //若在第一级缓存中没有获取到对象,并且singletonsCurrrentlyInCreation这个list包含该beanName,说明出现循环依赖
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
                //尝试从二级缓存中获取对象(二级缓存中的对象是一个早期对象)
                //早期对象:就是bean刚刚调用了构造方法,还来不及给bena的属性进行赋值的对象(纯净bean),就是早期对象
				singletonObject = this.earlySingletonObjects.get(beanName);
                //二级缓存中也没有获取到对象,allowEarlyReference为true(参数是由上一个方法传递进来的)
				if (singletonObject == null && allowEarlyReference) {
                    //直接从三级缓存中获取OjbectFactory对象,这个对象就是用来解决循环以来的关键所在
                    //在IOC后期的过程中,当bean调用了构造方法的时候,把早期对象包装成一个								//OjbectFactory暴露到三级缓存中
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
                        //在这里通过暴露的OjbectFactory包装对象中,通过他的getObject()来获取
                        //在这个环节中会调用到getEarlyBeanReference()来进行后置处理
						singletonObject = singletonFactory.getObject();
                        //把早期对象放置在二级缓存
						this.earlySingletonObjects.put(beanName, singletonObject);
                        //把ObjectFactory包装对象从三级缓存中删除掉
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}


public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
    	//加锁
		synchronized (this.singletonObjects) {
            //尝试从单例缓存池中获取对象
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				...
                ...
                ...
				}
                //在创建bean之前将该bean标记为正在创建
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
                    //初始化bean:这个过程其实是调用createBean()方法
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

//在创建bean之前将该bean标记为正在创建
protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}


#
@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

举例说明

  • A依赖B,A依赖C,C依赖A,B依赖A
1. for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//如果bean定义不是抽象的,是单例的,不是懒加载的,才会走getBean方法,此时beanName为A
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
					getBean(beanName);
			}
		}


2. protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    	//尝试去缓冲中获取对象,此时一二三级缓存都为空
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			//这里直接将增强A返回并且赋值给B中的属性
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
			//spring只能解决单例对象的setter注入的循环以来,不能解决构造器注入
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
				// 创建单例bean
				if (mbd.isSingleton()) {
                    //如果beanName和一个singletonFactory传入一个回调对象用于回调
                    //在#getSingleton()方法中会将当前bean标记为正在创建,放到singletonsCurrentlyInCreation.add(beanName)集合里面,后面会用来判断循环依赖,此时A被加入这个集合里面
                    //在回调完createBean(beanName, mbd, args)这个方法拿到这个返回值,将A加入到一次缓存中并且清除掉二三级缓存
					sharedInstance = getSingleton(beanName, () -> {
						try {
                            //进入创建bean的逻辑
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

		return (T) bean;
	}
    
3. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		//因为A是单例,允许循环依赖,当前正在创建
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
            //将beanName为A的钩子方法放入到这个三级缓存里面
            //将getEarlyBeanReference()放入到三级缓存里面,如果存在循环依赖的话会调用这个方法
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
            
            //在这里会创建B,走上面的流程,将B标记为正在创建,因为B依赖A,会去走创建A的流程,注意已经
           //addSingletonFactory已将AB都加入里面,A会getSingleton()从三级缓存中拿出来,如果为A设置了动态代理,会对A进行增强,并且加到二级缓存里面,将增强A注入到B的属性上面,当B走完这个整个过程,同样在这个方法会对A中的B属性进行填充,此时A和B都会创建完成
            //A依赖C,步骤和上面一样
            populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}

		return exposedObject;
	}
    
4. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        
		Object singletonObject = this.singletonObjects.get(beanName);
        
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
                
				singletonObject = this.earlySingletonObjects.get(beanName);
                //因为A现在只存到了三级缓存里面
				if (singletonObject == null && allowEarlyReference) 
                    //找到对应的钩子方法
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
                        //放到二级缓存里面,下次从二级缓存取,防止重复
						this.earlySingletonObjects.put(beanName, singletonObject);
                        //清除三级缓存
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

5. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
        //如果为A生成动态代理,在这里会为A实现这个功能
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值