bean的生命周期分析(二)

二、全流程梳理

2.5 获取Bean

  • 事实上,bean的生命周期分析(一)中的refresh方法帮我们创建好了BeanFactory,具体创建bean是另外的流程。
  • 为什么先讲获取。因为spring源码中是先从ioc容器中获取对象,获取不到再创建的。所以这里先从DefaultListableBeanFactory的doGetBean方法入手,它会委派给它的父类来处理,也就是AbstractBeanFactory。
    在这里插入图片描述

2.5.1 AbstractBeanFactory类

  • 入口是getBean方法
    在这里插入图片描述
  • 下面这个doGetBean是重点,关键部分用注释的形式标记了,下面会针对重点内容进行讲解。
protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

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

	// Eagerly check singleton cache for manually registered singletons.
	// 重点解析1 getSingleton 详见2.5.2
	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.
		// 如果我们已经在创建这个bean实例,则失败: 我们假设在循环引用中。
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// Check if bean definition exists in this factory.
		// 检查一下bean的定义是否已经存在于工厂中了,这里所谓的bean的定义就是beanDefinition,和之前的串起来了。	
		BeanFactory parentBeanFactory = getParentBeanFactory();
		// 一般不会来这里
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			// Not found -> check parent.
			String nameToLookup = originalBeanName(name);
			if (args != null) {
				// Delegation to parent with explicit args.
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
				// No args -> delegate to standard getBean method.
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}

		if (!typeCheckOnly) {
			markBeanAsCreated(beanName);
		}

		try {
			// 到这里 beanfactory中是存在beanDefinition的。
			// 合并父 BeanDefinition 与子 BeanDefinition 重点解析 详见2.5.3
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			// Guarantee initialization of beans that the current bean depends on.
			// 获取DependsOn
			String[] dependsOn = mbd.getDependsOn();
			// 有依赖的,要先初始化依赖的
			if (dependsOn != null) {
				for (String dep : dependsOn) {
					// 循环依赖
					/*
					* 检测是否存在 depends-on 循环依赖,若存在则抛异常。比如 A 依赖 B,
					 * B 又依赖 A,他们的配置如下:
					 *   <bean id="beanA" class="BeanA" depends-on="beanB">
					 *   <bean id="beanB" class="BeanB" depends-on="beanA">
					 *
					 * beanA 要求 beanB 在其之前被创建,但 beanB 又要求 beanA 先于它
					 * 创建。这个时候形成了循环,对于 depends-on 循环,Spring 会直接
					 * 抛出异常
					 */
					if (isDependent(beanName, dep)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
					}
					// 很好理解,既然你要创建的bean依赖其他bean,那就先把其他bean创建好
					// 注册依赖Bean
					registerDependentBean(dep, beanName);
					// 先获取依赖的Bean
					getBean(dep);
				}
			}

			// 一切就绪,终于可以来创建bean了。
			// Create bean instance.
			if (mbd.isSingleton()) {
				// 这里是个回调函数,先进入看getSingleton方法,这个和2.5.2里的getSingleton不是一个函数,但内容差不太多,详见2.5.4
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					public Object getObject() throws BeansException {
						try {
						    // 重点解析 4 见2.6.1
							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;
						}
					}
				});
				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 '" + scopeName + "'");
				}
				try {
					Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
						public Object getObject() throws BeansException {
							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;
		}
	}

	// Check if required type matches the type of the actual bean instance.
	if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
		try {
			return getTypeConverter().convertIfNecessary(bean, requiredType);
		}
		catch (TypeMismatchException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to convert bean '" + name + "' to required type [" +
						ClassUtils.getQualifiedName(requiredType) + "]", ex);
			}
			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
		}
	}
	return (T) bean;
}

2.5.2 重点解析1 getSingleton

涉及三级缓存。检查单例缓存是否有手动注册的单例,这里涉及到三级缓存。
singletonObjects:单例对象的缓存。成熟的对象。
earlySingletonObjects:早期单例对象的缓存。尚未成熟。
singletonFactories:单例工厂的缓存。

 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// Quick check for existing instance without full singleton lock
	// 取单例,取到成熟的对象最好了,直接返回
	Object singletonObject = this.singletonObjects.get(beanName);
	// 没取到 且 正在创建
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		// 从早期单例对象取,取到直接返回
		singletonObject = this.earlySingletonObjects.get(beanName);
		// 没取到 且 需要创建早期引用
		if (singletonObject == null && allowEarlyReference) {
			// 加锁
			synchronized (this.singletonObjects) {
				// Consistent creation of early reference within full singleton lock
				// 在加锁的情况下再次取单例,确定在这个过程中是否已经创建完成。取到直接返回
				singletonObject = this.singletonObjects.get(beanName);
				// 未取到
				if (singletonObject == null) {
					// 在加锁的情况下再次取早期单例,确定在这个过程中是否已创建早期单例对象。取到直接返回
					singletonObject = this.earlySingletonObjects.get(beanName);
					// 未取到
					if (singletonObject == null) {
						// 去单例工厂。未取到返回null
						ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
						// 取到单例工厂
						if (singletonFactory != null) {
							// 创建一个单例对象
							singletonObject = singletonFactory.getObject();
							// 放入早期单例对象
							this.earlySingletonObjects.put(beanName, singletonObject);
							// 从工厂中移除
							this.singletonFactories.remove(beanName);
						}
					}
				}
			}
		}
	}
	// 有4中情况的返回 单例对象、早期单例对象、单例工厂、null
	return singletonObject;
}

很显然,第一次创建bean时这里是取不到的,返回null。回到doGetBean主函数,我们继续往下看。

2.5.3 重点解析2 getMergedLocalBeanDefinition

这个函数是解决下面场景的:

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-autowire="byName">

    <bean id="parentBean" class="com.test.merge.ParentObject">
        <property name="score" value="1200"></property>
    </bean>
    <bean id="child" paren="parentBean" class="com.test.merge.ComplexObject">
        <property name="sex" value="1"></property>
        <property name="name" value="11221"></property>
    </bean>
</beans>

parent 这个属性有两个功能:

  • child 这个 bean 能够获取 parentBean 所定义的属性值。这个前提是 child 这个 bean 必须要拥有这些属性,不管是 child 自己有这个属性,还是从其父类中继承过来的属性。其实说到底还是 child 自己必须要有这个属性,因为从父类继承过来也是在解析过程中将父类的属性设置到子类的 BeanDefinition 中。如果 child 中属性的赋值跟 parentBean 中属性的赋值冲突的情况下,child 中的赋值会覆盖 parentBean 中的赋值。
  • child 不存在 class 这个属性时,可以使用 parentBean 的 class。
    parent 这个属性跟 bean 的继承没有关系。这个属性的存在是为了方便多个 bean 存在相同的属性时,可以共用同一个 parent,跟 bean 的继承有相似的作用,但它俩不是一个东西。这点大家要注意下。

getMergedLocalBeanDefinition 其实就是来处理 parent 这个属性的。当然其下层的 getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) 的这个方法不仅仅是处理 parent 属性。其实其还需要处理 containingBd 这个属性的,这个我们后续解释。

这个方法的目的就是将 parent 这个属性对应的 bean 定义中的信息设置到 child 中去。

这个方法的代码不是特别复杂,大家在了解了其用途之后可以自行下去看下。这里简单分析一下。

  • 首先第一层
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
	// Quick check on the concurrent map first, with minimal locking.
	// 看看有没有现成的merged的,有就直接取
	RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
	if (mbd != null) {
		return mbd;
	}
	return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
  • 第二层
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
		throws BeanDefinitionStoreException {

	return getMergedBeanDefinition(beanName, bd, null);
}

下面感兴趣可以自己看下。

protected RootBeanDefinition getMergedBeanDefinition(
		String beanName, BeanDefinition bd, BeanDefinition containingBd)
		throws BeanDefinitionStoreException {

	synchronized (this.mergedBeanDefinitions) {
		RootBeanDefinition mbd = null;

		// Check with full lock now in order to enforce the same merged instance.
		if (containingBd == null) {
			mbd = this.mergedBeanDefinitions.get(beanName);
		}

		if (mbd == null) {
			if (bd.getParentName() == null) {
				// Use copy of given root bean definition.
				if (bd instanceof RootBeanDefinition) {
					mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
				}
				else {
					mbd = new RootBeanDefinition(bd);
				}
			}
			else {
				// Child bean definition: needs to be merged with parent.
				BeanDefinition pbd;
				try {
					String parentBeanName = transformedBeanName(bd.getParentName());
					if (!beanName.equals(parentBeanName)) {
						pbd = getMergedBeanDefinition(parentBeanName);
					}
					else {
						BeanFactory parent = getParentBeanFactory();
						if (parent instanceof ConfigurableBeanFactory) {
							pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
						}
						else {
							throw new NoSuchBeanDefinitionException(parentBeanName,
									"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
									"': cannot be resolved without an AbstractBeanFactory parent");
						}
					}
				}
				catch (NoSuchBeanDefinitionException ex) {
					throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
							"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
				}
				// Deep copy with overridden values.
				mbd = new RootBeanDefinition(pbd);
				mbd.overrideFrom(bd);
			}

			// Set default singleton scope, if not configured before.
			if (!StringUtils.hasLength(mbd.getScope())) {
				mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
			}

			// A bean contained in a non-singleton bean cannot be a singleton itself.
			// Let's correct this on the fly here, since this might be the result of
			// parent-child merging for the outer bean, in which case the original inner bean
			// definition will not have inherited the merged outer bean's singleton status.
			if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
				mbd.setScope(containingBd.getScope());
			}

			// Only cache the merged bean definition if we're already about to create an
			// instance of the bean, or at least have already created an instance before.
			if (containingBd == null && isCacheBeanMetadata()) {
				this.mergedBeanDefinitions.put(beanName, mbd);
			}
		}

		return mbd;
	}
}

2.5.4 getSingleton(String beanName, ObjectFactory<?> singletonFactory)类

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	// 先上锁,锁singletonObjects对象
	synchronized (this.singletonObjects) {
		// 缓存里取一下
		Object singletonObject = this.singletonObjects.get(beanName);
		// 没取到
		if (singletonObject == null) {
			// 判断是否正在销毁,默认属性为false
			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 + "'");
			}
			// 单例创建前回调
			// 判断beanName在不在当前在创建检查中排除的bean名称缓存中
			// 加入当前正在创建的bean的名称缓存
			// 上面两个有一个失败false则抛BeanCurrentlyInCreationException异常
			// 下面附了beforeSingletonCreation的源码,一看就懂
			//protected void beforeSingletonCreation(String beanName) {
			//	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			//		throw new BeanCurrentlyInCreationException(beanName);
			//	}
			//}
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			try {
				// 这个singletonFactory就是回调函数,getObject()就是调用回调函数
				// 这里 getObject()返回是主流程中的return createBean(beanName, mbd, args);
				// 详见4.1
				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;
	}
}

可以看出整个逻辑还是比较简单的,重点是creatBean这个函数了。
欲知后事如何,请看下一篇。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CtrlZ1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值