Sping源码(九)—— Bean的初始化(非懒加载)— getMergedLocalBeanDefinition

序言

前两篇文章介绍了Bean初始化之前的一些准备工作,包括设置BeanFacroty的ConversionService属性以及将Bean进行冻结。这篇文章将会进入到preInstantiateSingletons方法。进一步了解Bean的初始化流程。

preInstantiateSingletons

	public void preInstantiateSingletons() throws BeansException {
		// 将所有BeanDefinition的名字创建一个集合
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// 触发所有非延迟加载单例bean的初始化,遍历集合的对象
		for (String beanName : beanNames) {
			// 合并父类BeanDefinition
 			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//省略部分代码....
		}
	}

分析

遍历BeanDefinitionName首先做的第一步是合并父类的beanDefinition。
合并过程大致可以分为以下几个步骤:

  1. mergedBeanDefinitions缓存中获取,缓存中有且不需要重新合并定义,则return
  2. 如果 containingBd 为null,则再次从缓存mergedBeanDefinitions中获取。
  3. 如果缓存中依然没有或者需要重新定义。
    3.1 获取parentName,如果parentName = null则创建(克隆)一个RootBeanDefinition封装当前Bean。
    3.2 parentName != null , 且当前beanName = parentName ,使用父工厂获取parentBeanName对应的合并BeanDefinition赋值给父BeanDefinition
    3.3 parentName != null , 且当前beanName != parentName , 如果父类尚未被加载,且父工厂属于ConfigurableBeanFactory
    调用父工厂进行merge操作。

源码

源码中涉及到很多方法的重载和重写,阅读源码时还要仔细分清。
getMergedLocalBeanDefinition
先尝试从缓存中拿。

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		// Quick check on the concurrent map first, with minimal locking.
		//先尝试从mergedBeanDefinitions缓存中取
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		//如果缓存中有 && 不需要重新合并定义 则直接return
		if (mbd != null && !mbd.stale) {
			return mbd;
		}
		//获取 beanName对应的合并BeanDefinition,如果是ChildBeanDefinition 则需要合并
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

getMergedBeanDefinition
整体流程步骤上面大致已经介绍。

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

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

			// Check with full lock now in order to enforce the same merged instance.
			// 先尝试从mergedBeanDefinitions缓存中取
			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null || mbd.stale) {
				previous = mbd;
				//parentName为null,说明没有父类BeanDefinition需要合并
				if (bd.getParentName() == null) {
					// Use copy of given root bean definition.
					//如果当前的bd是RootBeanDefinition 则直接克隆
					if (bd instanceof RootBeanDefinition) {
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						//否则则创建RootBeanDefinition
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// Child bean definition: needs to be merged with parent.
					//parentName不为null,则需要合并
					BeanDefinition pbd;
					try {
						//通过transformedBeanName方法获取parentBean的最终别名
						String parentBeanName = transformedBeanName(bd.getParentName());
						//如果当前beanName不等于parentBeanName
						if (!beanName.equals(parentBeanName)) {
							// 获取parentBeanName的"合并的"BeanDefinition赋值给pdb
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							//如果当前beanName等于parentBeanName,则获取父类工厂
							BeanFactory parent = getParentBeanFactory();
							//如果父类工厂是ConfigurableBeanFactory,则使用父工厂获取parentBeanName对应的合并BeanDefinition赋值给pdb
							if (parent instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
							}
						}
					}
					// Deep copy with overridden values.
					//生成RootBeanDefinition
					mbd = new RootBeanDefinition(pbd);
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				//设置默认的scope
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(SCOPE_SINGLETON);
				}

				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}
				//暂时缓存合并的bean定义(稍后可能仍会重新合并以获取元数据更正),如果没有传入包含bean定义 且 当前工厂是同意缓存bean元数据
				//cacheBeanMetadata:默认为true 代表是缓存bean元数据,还是在每次访问时重新获取它
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}
			if (previous != null) {
				copyRelevantMergedBeanDefinitionCaches(previous, mbd);
			}
			return mbd;
		}
	}

getMergedBeanDefinition
父类调用的((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);

public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
		//获取实际的beanName
		String beanName = transformedBeanName(name);
		// Efficiently check whether bean definition exists in this factory.
		// 当前beanName在当前工厂的beanDefinitionMap中不存在 && 父工厂 属于 ConfigurableBeanFactory

		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
			//使用父工厂返回beanName的合并BeanDefinition【如有必要,将子bean定义与其父级合并】
			return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
		}
		// Resolve merged bean definition locally.
		//本地解决合并的bean定义
		return getMergedLocalBeanDefinition(beanName);
	}

流程图

在这里插入图片描述

总结

总结:
没有父类就创建一个RootBeanDefinition封装信息、放入缓存后返回。
有父类则调用父类工厂进行merge操作后,同样创建RootBeanDefinition封装父类信息后返回给子类,子类拿到父类返回的BeanDefinition后再次封装进RootBeanDefinition,设置信息后、放入缓存返回。

值得一提的是mergedBeanDefinitions变量,在Spring中有很多类似的应用,将不太变化且经常可以用到的东西放入缓存中,用时先在缓存中获取,包括beanDefinitionMap等变量都是如此。

mergedBeanDefinitions变量其实我们并不是第一次见到,源码中在执行invokeBeanFactoryPostProcessors方法时,会调用beanFactory.getBeanNamesForType方法获取系统中实现了BeanFactoryPostProcessorBeanDefinitionRegistoryPostProcessor的类。

beanFactory.getBeanNamesForType方法中就有beaDefinition的merge操作,感兴趣可以再了解了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值