Spring源码分析五 :bean的获取③ - getSingleton

在 Spring 源码分析四 :bean的加载② - doGetBean详解 中,我们知道
DefaultSingletonBeanRegistry#getSingleton(java.lang.String, ObjectFactory<?>)这一步创建了bean,如下图:

在这里插入图片描述

 

到了这一步,Spring 就基本对 Bean已经创建好了 不抱什么希望了,所以着手开始自己创建bean。
本文就来分析 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法整个流程。

二、获取单例 - getSingleton
如下, 是整个 getSingleton方法的代码,做了一些基本注释

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		// 因为创建过程中需要操作 singletonObjects。所以需要加锁
		synchronized (this.singletonObjects) {
			// 1. 再次尝试获取bean,判断bean是否已经加载。如果加载直接返回。
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				// 2. 判断,如果当前beanFactory正在被销毁则直接抛出异常,不允许创建单例bean
				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 + "'");
				}
				// 3. 做一些bean创建前的准备工作: 记录beanName 正在加载的状态(添加到 singletonsCurrentlyInCreation 缓存中),若bean已经正在加载,则抛出异常。为了解决循环引用的问题
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 4. 通过回调方式获取bean实例。
					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;
					}
					// 5. 加载单例后的处理方法调用 : 删除bean正在创建的记录(从 singletonsCurrentlyInCreation  中移除 beanName)
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					// 6. 加入到缓存中,并删除加载bean过程中所记录的各种辅助状态
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

	...
	// 主要还是对几个缓存map的操作
	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);
		}
	}
	...
	
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}
	...
	protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}


上面的代码注释也比较清楚,基本流程如下:

this.singletonObjects.get(beanName); :再次尝试从缓存中获取bean,若获取到,则直接返回。
if (this.singletonsCurrentlyInDestruction) :未获取到检测bena是否正在销毁,若是则抛出异常
beforeSingletonCreation 方法中记录bean正在创建的状态将beanName添加到singletonsCurrentlyInCreation集合中)。在循环依赖时可根据此判断。
singletonObject = singletonFactory.getObject(); :调用 ObjectFactory.getObject() 方法来实例化bean
afterSingletonCreation 方法移除bean正在夹杂的状态
addSingleton(beanName, singletonObject); : 对各种缓存状态做处理。
流程图如下所示 :

在这里插入图片描述

 

可以非常直观的看出, getSingleton 方法中的关键逻辑非常简单,bean创建的具体逻辑在 singletonObject = singletonFactory.getObject(); 中,所以下面继续去分析singletonFactory.getObject()中做了什么。

三、创建bean - createBean概述
上面可以看到,主要步骤还是在回调的 getObject() 方法中。那么我们来看看在bean加载过程中的FactoryBean做了什么。代码如下:

在这里插入图片描述
兜了一大圈关键代码还是在createBean 方法里。接下来,我们就来仔细分析一下 createBean 方法。

 

AbstractAutowireCapableBeanFactory#createBean 方法代码如下 ,附带部分注释:
    

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


        RootBeanDefinition mbdToUse = mbd;


        // 1. 锁定class, 根据mdb和 beanName 解析出来 class
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
            // 2. 验证及准备覆盖的方法
            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.
            // 3. 调用BeanProcessors的方法来替代真正的实例
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            // 如果后处理器真的实现了,则直接返回使用后处理器的bean
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            // 4.  创建bean 的 真正方法
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值