spring 源碼分析01

spring中獲取bean的常見的方式,通常從BeanFactory中或者ApplicationContext中獲取。由於ApplicationContext接口繼承了BeanFactory接口,因此直接講BeanFactory.getBean(String beanName)
AbstractBeanFactory的getBean調用的是該類的doGetBean方法html

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

		final String beanName = transformedBeanName(name);
		Object bean;

		// 從spring的三級緩存中獲取bean---解決循環依賴的關鍵
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance: // We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

            //忽略部分代碼
			.....

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				//忽略部分代碼,getDependsOn依賴bean先加載
			    .....

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							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; } } //忽略部分代碼--類型的校驗 ..... } return (T) bean; } 複製代碼

上述的代碼中大體的流程以下:spring

  1. 從Spring維護的三級緩存中獲取一個singleton bean,獲取成功直接返回
  2. 判斷該bean是否處於建立中,若是是說明出現了循環依賴,拋異常
  3. 根據bean的做用域,分別用不一樣的方式獲取bean,若是獲取不到最終調用的都是同一個createBean方式
  4. getObjectForBeanInstance 若是上述方法獲取到的是一個FactoryBean的狀況下,須要從裏面獲取對應的咱們須要的Bean

下面分析下singleton bean的獲取緩存

// Create bean instance.
if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
複製代碼
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);
				//定義異常
				...
				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) {
				    //封裝異常
					...
				}
				finally {
					...
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}
複製代碼
  1. 由於singleton的bean只能存在一個,因此對singletonObjects這個緩存作加鎖獲取
  2. 作循環依賴判斷
  3. beforeSingletonCreation(beanName);//也就是把這個beanName標記成正在建立中
  4. 經過singletonFactory的方法獲取bean --> 也就是調用createBean方法
  5. afterSingletonCreation(beanName);//去除該beanName正在建立中的標記
  6. 若是是新建立的singleton的bean的話,把他加入singletonObjects緩存中
  7. 這個singletonObjects緩存也就是上面所說的三級緩存的中的第一級(具體後續再說)

無論是singleton仍是Prototype仍是其餘的scope,在從做用域中獲取不到bean的狀況下,都是調用的createBeanbash

  • 知識點梳理:
  1. FactoryBean:www.cnblogs.com/davidwang45…
  2. bean的做用域:
    1. singleton:整個容器中保留一份
    2. prototype:每次使用的時候,建立新的
    3. 其餘scope
      1. SimpleThreadScope
      2. RequestScope
      3. SessionScope
相關文章
相關標籤/搜索