spring源码分析系列-浅谈spring循环依赖及三级缓存

        spring的循环依赖是个老生常谈的话题,熟悉spring或者准备面试的同学肯定都在熟悉不过了。闲来无事记录下我对spring循环依赖问题及三级缓存的理解。

        首先来看下准备工作。首先准备A、B两个类互相依赖,一个config类、一个测试启动类。

A类如下:加上注解,一个属性b,get set方法,没了!


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

@Component
public class A {

	@Autowired
	private B b;

	public B getB() {
		return b;
	}
	public void setB(B b) {
		this.b = b;
	}
}

B类如下:加上注解,一个属性a,一个测试用的query方法,get set 方法,没了!

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

@Component
public class B {

	@Autowired
	private A a;

	public void query(){
		System.out.println("bbbbb");
	}

	public A getA() {
		return a;
	}
	public void setA(A a) {
		this.a = a;
	}
}

Config类如下:扫描包,没了!

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.zlb.ioc")
public class IocConfig {
	
}

测试启动类如下:构建spring环境,从容器中获取bean,调用方法。没了!

import com.zlb.ioc.circle.A;
import com.zlb.ioc.config.IocConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Demo {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(IocConfig.class);
		A a = context.getBean(A.class);
		a.getB().query();
	}
}

        我们来扫个盲,说两个前置知识:

1.我们都知道spring是一个容器,那么我们想从容器中获取一个bean的时候一定会调用一个getBean方法,无论是我们手动从context获取还是属性注入的时候spring内部去获取,都是走这个getBean方法。

2.spring中的三级缓存指的是下边这三个货。其实就是三个map,只不过泛型有一个特殊一点。至于谁是一级谁是二级这个仁者见仁,本文直接用变量名以防混乱。


	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

         在看源码之前我们通过文字捋一遍整体流程:

  1. 首先创建对象A,调用getBean("a")方法。
  2. 从缓存singletonFactories中获取对象A,此时获取不到,于是反射创建对象A。
  3. 将对象A标记为正在创建中。
  4. 将对象A放进缓存singletonFactories。
  5. 创建A的过程中发现要给属性b赋值,于是满世界找对象B。
  6. 通过getBean("b")方法获取B对象。
  7. 创建B的过程发现要给属性a赋值,于是满世界找对象A。
  8. 再次调用getBean("a")方法获取A对象。
  9. 从缓存singletonFactories中拿到A对象返回B,于是B对象创建完成并放进缓存。
  10. B创建完成于是返回给第5步,最终A对象创建完成。

最后走进spring源码,看看大佬们创造的艺术世界:

1.一切都要从spring容器初始化开始说起:

public class Demo {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(IocConfig.class);
		A a = context.getBean(A.class);
		a.getB().query();
	}
}

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
        //进入refresh方法
		refresh();
}

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 进入这个方法
		finishBeanFactoryInitialization(beanFactory);			
	}
}

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 进入这个方法 具体实现是DefaultListableBeanFactory
	beanFactory.preInstantiateSingletons();		
}

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

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						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(beanName);
						}
					}
				}
				else {
					//进入这个方法
					getBean(beanName);
				}
			}
		}

2.重点终于来了,这是第一次调用getBean方法,此时是获取(创建)对象A:

@Override
	public Object getBean(String name) throws BeansException {
        //进去
		return doGetBean(name, null, null, false);
	}

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

		String beanName = transformedBeanName(name);
		Object beanInstance;

		// Eagerly check singleton cache for manually registered singletons.
		// 首先尝试从缓存中去获取 第一次肯定是获取不到的
		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 + "'");
				}
			}
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			try {

				// Create bean instance.
				if (mbd.isSingleton()) {
					//创建bean实例
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
			}
		}

		return adaptBeanInstance(name, beanInstance, requiredType);
	}

3.我们看下getSingleton(beanName)这个方法是怎么获取的?

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		// 首先从singletonObjects缓存中获取 第一次肯定拿不到
		Object singletonObject = this.singletonObjects.get(beanName);
		//第二个条件是判断当前bean是否正在创建中(正在创建中的bean都会放在一个集合里边),第一次创建的时候当前bean肯定不在这个集合中 所以这个if判断不成立 直接返回null
		// 但是如果是第二次来获取,也就是说循环依赖中给B对象的a属性赋值的时候,此时a已经在集合中了即a已经是正在创建中的状态了,所以if条件成立。
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//从earlySingletonObjects缓存中获取 无论是第一次还是第二次都拿不到
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) { //allowEarlyReference恒为true
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					// 从singletonObjects缓存中获取 无论是第一次还是第二次都拿不到
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						//拿不到
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							//第二次获取的时候singletonFactories缓存中已经有值了 只不过存的是一个工厂的函数式接口
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								//此时此刻就会去执行函数式接口的具体实现 也就是AbstractAutowireCapableBeanFactory.getEarlyBeanReference方法
								singletonObject = singletonFactory.getObject();
								//放入earlySingletonObjects缓存中
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

4.再来看下创建对象的getSingleton方法:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			// 再次从singletonObjects缓存中获取 肯定还是获取不到
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				//将正在创建的对象放到集合中 表示:当前对象正在创建中
				beforeSingletonCreation(beanName);

				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//此处是调用方法入参中的第二个参数 即:lambda表达式
					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) {
					//将当前bean放入singletonObjects缓存中
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

5.看看createBean方法中的doCreateBean(beanName, mbdToUse, args)方法:

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//反射创建bean实例
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//将当前半成品bean放入singletonFactories缓存中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			//属性赋值
			populateBean(beanName, mbd, instanceWrapper);
			//回调初始化方法
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		return exposedObject;
	}

6.populateBean方法中会给A对象的b属性赋值,此时会再次调用getBean方法,只不过此时要获取的是B对象了。代码和上边一模一样,直到再次执行到populateBean方法给B对象的a属性赋值的时候。此时会第三次执行getBean方法,不过此时获取的又是A对象了。那我们再看下第二次获取A时从缓存获取时候的逻辑:

@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		// 首先从singletonObjects缓存中获取 第一次肯定拿不到
		Object singletonObject = this.singletonObjects.get(beanName);
		//第二个条件是判断当前bean是否正在创建中(正在创建中的bean都会放在一个集合里边),第一次创建的时候当前bean肯定不在这个集合中 所以这个if判断不成立 直接返回null
		// 但是如果是第二次来获取,也就是说循环依赖中给B对象的a属性赋值的时候,此时a已经在集合中了即a已经是正在创建中的状态了,所以if条件成立。
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//从earlySingletonObjects缓存中获取 无论是第一次还是第二次都拿不到
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) { //allowEarlyReference恒为true
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					// 从singletonObjects缓存中获取 无论是第一次还是第二次都拿不到
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						//拿不到
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							//第二次获取的时候singletonFactories缓存中已经有值了 只不过存的是一个工厂的函数式接口
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								//此时此刻就会去执行函数式接口的具体实现 也就是AbstractAutowireCapableBeanFactory.getEarlyBeanReference方法
								singletonObject = singletonFactory.getObject();
								//放入earlySingletonObjects缓存中
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

很明显此时已经从singletonFactories缓存中拿到了A对象,那么就可以继续B对象的创建过程了。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			// 再次从singletonObjects缓存中获取 肯定还是获取不到
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				//将正在创建的对象放到集合中 表示:当前对象正在创建中
				beforeSingletonCreation(beanName);

				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//此处是调用方法入参中的第二个参数 即:lambda表达式
					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) {
					//将当前bean放入singletonObjects缓存中
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

addSingleton(beanName, singletonObject)这个方法正式将B对象放进了singletonObjects缓存中,最后将B对象返回。此时给A对象的b属性也就赋值成功了。

最后A对象回调init方法执行后置处理器等等完成其初始化。行棋至此A B两个对象都已经创建完成。

最后我们通过一个流程图来回顾一下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值