Spring5源码浅析(七)—DefaultSingletonBeanRegistry(上)

       在上一篇《Spring5源码浅析(六)—SimpleAliasRegistry》中,我们分析了SimpleAliasRegistry的源码,本篇呢,我们继续沿着DefaultListableBeanFactory的继承线往下走,开始分析DefaultSingletonBeanRegistry. 这个类除了是SimpleAliasRegistry的子类之外,它还实现了SingletonBeanRegistry这个接口.在《Spring5源码浅析(三)—ConfigurableBeanFactory》这篇博文中,我们知道SingletonBeanRegistry接口提供了统一的方式来管理单例Bean.在这个接口中有六个函数,分别是:registerSingleton(String beanName,Object singletonObject),getSingleton(String beanName),containsSingleton(String beanName),getSingletonNames(),getSingletonCount(),getSingletonMutex()。这也是我们今天借以分析SingletonBeanRegistry的主线.

       DefaultSingletonBeanRegistry是一个实现了SingletonBeanRegistry接口的一般性的注册表,主要为共享bean实例而存在的.它提供了一些接口来获取那些被当前注册表的所有调用者所共享出来的单例Bean实例的名称.也支持DisposableBean实例的注册信息(这类的Bean可能和注册单例一致也可能不一致),会在这个Registry关闭的时候销毁.Bean之间的依赖也会被注册以便可以执行一个合理的关闭顺序.这个类提炼出了单例Bean实例的通用管理方式作为一个基础类为BeanFactory的实现而服务.值得注意的是ConfigurableBeanFactory也继承了SingletonBeanRegistry接口.并且在这个类里既没有Bean Definition的概念,也没有为Bean实例提供特定的创建处理,这是与AbstractBeanFactory和DefaultListableBeanFactory(DefaultListableBeanFactory继承了DefaultSingletonBeanRegistry)完全不同的.

      我们现在可以来看一下他的api实现,首先是registerSingleton(String beanName,Object singletonObject)这个接口,其源码如下所示:

@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		Assert.notNull(beanName, "Bean name must not be null");
		Assert.notNull(singletonObject, "Singleton object must not be null");
		synchronized (this.singletonObjects) {
			Object oldObject = this.singletonObjects.get(beanName);
			if (oldObject != null) {
				throw new IllegalStateException("Could not register object [" + singletonObject +
						"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
			}
			addSingleton(beanName, singletonObject);
		}
	}

	/**
	 * Add the given singleton object to the singleton cache of this factory.
	 * <p>To be called for eager registration of singletons.
	 * @param beanName the name of the bean
	 * @param singletonObject the singleton object
	 */
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

	/**
	 * Add the given singleton factory for building the specified singleton
	 * if necessary.
	 * <p>To be called for eager registration of singletons, e.g. to be able to
	 * resolve circular references.
	 * @param beanName the name of the bean
	 * @param singletonFactory the factory for the singleton object
	 */
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

      在这个函数中,首先判断了Bean的名称是否为空,其次判断了要注册的单例对象是否为空,紧接着开始对存储单例对象的ConcurrentHashMap进行上锁操作,上锁之后,它首先根据Bean的名称去判断,这个名字是否被注册过,如果没有,开始执行addSingleton这个函数来执行具体的注册操作.

       而在addSingleton(beanName,singletonObject)这个函数中,他也是首先做了锁的操作,其次他首先将给定的对象放到singletonObjects的集合中,这个集合主要是应用于单例对象的缓存,其次,他将同名的单例工厂对象给移除,然后又从早期的单例对象池中将同名的单例对象移除,最后会将单例对象在registeredSingletons集合里进行登记.

      在addSingleton(beanName,singletonObject)函数的后面,它还有一个类似的函数,叫addSingletonFactory(beanName,singletonFactory)函数,这个函数主要是应用于添加对象工厂的,因此他的操作与上面的操作类似,他判断如果singletonObjects集合里不包含指定名称的bean,他才会往singletonFactories里存入ObjectFactory对应的bean实例信息,然后也会在registeredSingletons集合中进行登记.这里需要特别标记一下,addSingleFactory有一个作用就是解决循环依赖,那循环依赖怎么解决,我们等会儿补充说明.

        刚刚在研究的时候,我们发现在spring里有几个集合,其中一个是singletonObjects,一个是registeredSingletons,一个是singletonFactories,最后一个是earlySingletonObjects如下所示,其中,singletonObjects,我们刚刚已经介绍过了,存放的都是单例非工厂对象,而singletonFactories集合则存放的是单例工厂对象,而这两个无论哪一个,都需要在registeredSingletons集合中进行登记.

/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** Set of registered singletons, containing the bean names in registration order. */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

       至于earlySingletonObjects这个集合,在之前的register以及add方法里,我们都没有看到有bean的添加,然而在getSingleton函数却出现了bean在earlySingletonObjects中的添加,现在我们来具体看一下:

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

	/**
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference whether early references should be created or not
	 * @return the registered singleton object, or {@code null} if none found
	 */
	@Nullable
	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);
				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;
	}

因为getSingleton(String beanName)这个函数,本质上调用的getSingleton(String beanName,boolean allowEarlyReference),所以我们直接来看getSingleton(String,boolean)这个函数.首先从singletonObjects集合中取同名的,如果singletonObjects集合包含有同名的,则直接返回.如果没有,就判断该对象是否正在创建中,如果该对象正在创建中,就锁定singletonObjects集合,然后从earlySingletonObjects集合中去取,如果earlySingletonObjects中也不存在,并且allowEarlyReference为true,就像getSintleton中所写的那样,就从singletonFactories中获取同名的ObjectFactory,如果singletonFactories中确实找到了一个同名的ObjectFactory,就获取ObjectFactory中存放的对象,然后将该对象放入到earlySingletonObjects中,然后把同名的ObjectFactory从singletonFactories中移除.

       这里有两个东西需要特别说明一下,首先就是ObjectFactory,这个ObjectFactory是一个函数式接口,它里面唯一的一个函数就是getObject,典型地使用是在每次调用的时候都能够返回一个原型对象的新实例.这个接口与FactoryBean很像.但是FactoryBean的实现通常都是要作为SPI实例在BeanFactory中被定义的,而ObjectFactory的实现则通常都是给其他的Bean提供的一个API.

       其次,则是allowEarlyReference,这个字段在读了源码之后,我们就明白了是用来确定是否允许从singletonFactories中获取单例对象.

       我们现在来看循环引用问题,所谓循环引用就是只我有两个实体类,其中A依赖于B,B依赖于A.一般来说依赖有两种形式,第一种是通过构造参数进行初始化引用,第二种就是通过字段的setter.在之前的API介绍中,我们知道在Spring中,有一些API是专门做实例化的,而有一些则是专门做初始化的.

       简单介绍完背景之后,我们现在来看对象的创建,这里提前透露一点,就是addSingletonFactory这个函数是在AbstractAutowireCapableBeanFactory的doCreateBean里被调用的,并且是在createBeanInstance之后,由此,我们大略地可以知道在完成Bean的创建之后,会将Bean的实例放入到我们的singletonFactories里进行暴露.具体地我们可以到AbstractAutowireCapableBeanFactory中去进行验证.

       假如我们的实体类A完成了创建,并在singletonFactories里进行了暴露,然后执行初始化的时候发现需要依赖于B,于是就开始用getSingleton(B),结果B没有,就开始走B的创建流程,结果B在初始化的时候发现需要依赖于A,于是就getSingleton(A),然后先尝试从singletonObjects中获取(一级缓存),如果没有,就尝试从earlySingleObjects中去获取(二级缓存),发现也没有,因此就从singletonFactories中获取(三级缓存).因为A在创建完成之后,已经在singletonFactories里进行标记了,所以此时是可以拿到的,因此B是可以正常进行初始化的,而B初始化完成之后,A就可以拿到已经初始化完毕的B的实例了,也就完成了初始化,从而进入到了singleObjects集合里(一级缓存).从而我们也就能够理解,为何Spring无法解决A的构造器里依赖了B,而B的构造器里依赖了A这种循环引用的场景了.毕竟想进入到singletonFactories的前提就是完成实例化.

/**
	 * Return the (raw) singleton object registered under the given name,
	 * creating and registering a new one if none registered yet.
	 * @param beanName the name of the bean
	 * @param singletonFactory the ObjectFactory to lazily create the singleton
	 * with, if necessary
	 * @return the registered singleton object
	 */
	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) {
				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 {
					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;
		}
	}

	/**
	 * Register an Exception that happened to get suppressed during the creation of a
	 * singleton bean instance, e.g. a temporary circular reference resolution problem.
	 * @param ex the Exception to register
	 */
	protected void onSuppressedException(Exception ex) {
		synchronized (this.singletonObjects) {
			if (this.suppressedExceptions != null) {
				this.suppressedExceptions.add(ex);
			}
		}
	}

/**
	 * Callback before singleton creation.
	 * <p>The default implementation register the singleton as currently in creation.
	 * @param beanName the name of the singleton about to be created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

	/**
	 * Callback after singleton creation.
	 * <p>The default implementation marks the singleton as not in creation anymore.
	 * @param beanName the name of the singleton that has been created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}

这个函数看起来很长,很吓人,其实没有什么特别的地方,主要是为了从ObjectFactory中获取单例对象,并且在获取之后,会将该对象添加到singleObjects并从singleFactories中移除,相当于从三级缓存一下移动到了一级缓存.并且在这里还添加了单例创建前的操作(beforeSingletonCreation)以及单例创建后的操作(afterSingletonCreation).这两个函数子类是可以进行实现覆盖的.

       鉴于篇幅问题,本次分析就到这里,下次我们继续来看DefaultSingletonBeanRegistry这个类.如果你在阅读本篇博文的时候,发现有什么问题或者好的建议可以留言或者发email(jacob_earl@163.com).可参考《Spring 如何解决循环依赖的问题》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值