admin管理员组

文章数量:1590132

        在前两篇《Spring5源码浅析(七)—DefaultSingletonBeanRegistry(上)》《Spring5源码浅析(七)—DefaultSingletonBeanRegistry(下)》中,我给大家详细分析了DefaultSingletonBeanRegistry这个类,从中我们知道DefaultSingletonBeanRegistry主要侧重于Bean的注册,销毁,以及依赖关系(关联关系)的注册和销毁。本篇呢,我们继续沿着DefaultListableBeanFactory的继承线往下移,所以我们来看一下DefaultSingletonBeanRegistry的子类---FactoryBeanRegistrySupport.

      我们首先来看这个抽象类中,最长的方法getObjectFromFactoryBean,源码如下所示:

/**
	 * Obtain an object to expose from the given FactoryBean.
	 * @param factory the FactoryBean instance
	 * @param beanName the name of the bean
	 * @param shouldPostProcess whether the bean is subject to post-processing
	 * @return the object obtained from the FactoryBean
	 * @throws BeanCreationException if FactoryBean object creation failed
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

       在getObjectFromFactoryBean函数中,主要处理两个问题,第一个是工厂是不是单例的,第二个是这个Bean是否需要进一步处理.

         首先,如果传入的工厂是单例的,并且要获取的beanName已经被实例化了,就会使用父类DefaultSingletonBeanRegistry的getSingletonMutex来锁定singletonObjects这个集合(该集合的详细介绍可参考《Spring5源码浅析(七)—DefaultSingletonBeanRegistry(上)》),然后首先从缓存factoryBeanObjectCache中获取bean,如果缓存中已经有了,就直接返回该对象.如果缓存中没有,就调用doGetObjectFromFactoryBean方法来获取object,调用完成之后,因为有可能在调用doGetObjectFromFactoryBean的过程中,该Bean被放到了factoryBeanObjectCache中,所以需要再次校验,如果此时发现缓存中已经有了,那就直接返回就行了,如果此时还没有,我们就会判断一下在父类DefaultSingletonBeanRegistry中的singletonObjects是否已经包含该实例了,如果已经包含了,我们就把这个对象存放到本地缓存(factoryBeanObjectCache)中,在存放缓存之前,会根据shouldPostProcess来决定是否对当前这个对象做进一步的操作,比如为当前这个对象应用beforeSingletonCreation,调用postProcessObjectFromFactoryBean,以及afterSingletonCreation这几个函数.

        其次,如果工厂不是单例的或者要获取的beanName没有被实例化,就会使用doGetObjectFromFactoryBean来获取实例,并根据shouldPostProcess来决定是否为这个对象执行postProcessObjectFromFactoryBean这个函数,最后进行返回.

        现在来看FactoryBeanRegistrySupport中第二长的函数doGetObjectFromFactoryBean,源码如下所示:

    /**
	 * Obtain an object to expose from the given FactoryBean.
	 * @param factory the FactoryBean instance
	 * @param beanName the name of the bean
	 * @return the object obtained from the FactoryBean
	 * @throws BeanCreationException if FactoryBean object creation failed
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

       这个方法看似很长,但实际上就做了一件事儿,就是调用传入的FactoryBean的getObject方法获取一个对象,如果FactoryBean中没有获取到,那就先看这个Bean是不是在创建中,如果是,就抛出一个异常,如果不是,就返回一个NullBean();

      现在我们来看剩下的几个方法,源码如下所示:

    /**
	 * Determine the type for the given FactoryBean.
	 * @param factoryBean the FactoryBean instance to check
	 * @return the FactoryBean's object type,
	 * or {@code null} if the type cannot be determined yet
	 */
	@Nullable
	protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
		try {
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged((PrivilegedAction<Class<?>>)
						factoryBean::getObjectType, getAccessControlContext());
			}
			else {
				return factoryBean.getObjectType();
			}
		}
		catch (Throwable ex) {
			// Thrown from the FactoryBean's getObjectType implementation.
			logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
					"that it should return null if the type of its object cannot be determined yet", ex);
			return null;
		}
	}

	/**
	 * Obtain an object to expose from the given FactoryBean, if available
	 * in cached form. Quick check for minimal synchronization.
	 * @param beanName the name of the bean
	 * @return the object obtained from the FactoryBean,
	 * or {@code null} if not available
	 */
	@Nullable
	protected Object getCachedObjectForFactoryBean(String beanName) {
		return this.factoryBeanObjectCache.get(beanName);
	}

    /**
	 * Post-process the given object that has been obtained from the FactoryBean.
	 * The resulting object will get exposed for bean references.
	 * <p>The default implementation simply returns the given object as-is.
	 * Subclasses may override this, for example, to apply post-processors.
	 * @param object the object obtained from the FactoryBean.
	 * @param beanName the name of the bean
	 * @return the object to expose
	 * @throws org.springframework.beans.BeansException if any post-processing failed
	 */
	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
		return object;
	}

	/**
	 * Get a FactoryBean for the given bean if possible.
	 * @param beanName the name of the bean
	 * @param beanInstance the corresponding bean instance
	 * @return the bean instance as FactoryBean
	 * @throws BeansException if the given bean cannot be exposed as a FactoryBean
	 */
	protected FactoryBean<?> getFactoryBean(String beanName, Object beanInstance) throws BeansException {
		if (!(beanInstance instanceof FactoryBean)) {
			throw new BeanCreationException(beanName,
					"Bean instance of type [" + beanInstance.getClass() + "] is not a FactoryBean");
		}
		return (FactoryBean<?>) beanInstance;
	}

	/**
	 * Overridden to clear the FactoryBean object cache as well.
	 */
	@Override
	protected void removeSingleton(String beanName) {
		synchronized (getSingletonMutex()) {
			super.removeSingleton(beanName);
			this.factoryBeanObjectCache.remove(beanName);
		}
	}

	/**
	 * Overridden to clear the FactoryBean object cache as well.
	 */
	@Override
	protected void clearSingletonCache() {
		synchronized (getSingletonMutex()) {
			super.clearSingletonCache();
			this.factoryBeanObjectCache.clear();
		}
	}

	/**
	 * Return the security context for this bean factory. If a security manager
	 * is set, interaction with the user code will be executed using the privileged
	 * of the security context returned by this method.
	 * @see AccessController#getContext()
	 */
	protected AccessControlContext getAccessControlContext() {
		return AccessController.getContext();
	}

        第一个getTypeForFactoryBean是为了获取factoryBean中的ObjectType.

        第二个getCachedObjectForFactoryBean则是从缓存(factoryBeanObjectCache)中获取一个指定Bean.

        第三个postProcessObjectFromFactoryBean,为给定的Bean做后继处理,这里是空的,但因为他的修饰符是protected,所以在子类,肯定有对他的处理.

        第四个getFactoryBean,获取给定Bean的FactoryBean,这里处理的方式也很简单,就只是对给定的beanInstance做了一次强制转换,当然如果beanInstance不是FactoryBean的子类,就直接抛出异常.

       第五个removeSingleton,这个函数是对父类DefaultSingletonBeanRegistry中removeSingleton的一个重载覆盖,他除了执行父类的removeSingleton之外,另外做了一个本地缓存的移除.

       同样,第六个clearSingletonCache,这个函数也是对父类DefaultSingletonBeanRegistry中clearSingletonCache的一个覆盖,他除了执行父类的clearSingletonCache逻辑之外,还对本地缓存做了一个清除.

       最后一个就是getAccessControlContext.说起这个函数,我们不得不提一下,如果大家注意的话,无论是getTypeForFactoryBean还是doGetObjectFromFactoryBean,亦或是getAccessControlContext,都使用了JDK所提供的资源权限控制,更倾向于从操作系统层面来强调资源调度上下文的使用,这是我们在研发的时候极少考虑的.

       好了,我们对FactoryBeanRegistrySupport类的分析就到这里,如果你有什么问题或者有什么好的建议,欢迎留言或email(jacob_earl@163).我们下次将为大家分析AbstractBeanFactory.

本文标签: 源码FactoryBeanRegistrySupport