栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring源码之BeanDefinition合并流程源码解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring源码之BeanDefinition合并流程源码解析

Spring的BeanDefinition合并流程
  • 背景
  • 合并BeanDefinition

背景

spring通过扫描得到所有的BeanDefination之后,就可以根据BeanDefination创建Bean对象了。在配置文件(spring.xml)中定义如下代码。默认是单例的。




MainClass中进行验证是否是单例

@ComponentScan("com.xyz.lifeStyle")
public class MainClass {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
		Parent parent = context.getBean("parent", Parent.class);
		Parent parent2 = context.getBean("parent", Parent.class);
		System.out.println("打印第一次parent的Scope:"+parent);
		System.out.println("打印第二次parent的Scope:"+parent2);

		Child child = context.getBean("child", Child.class);
		Child child2 = context.getBean("child", Child.class);

		System.out.println("打印第一次child的Scope:"+child);
		System.out.println("打印第二次child2的Scope:"+child2);
	}

}

验证结果如下:打印出的类都是相同的bean

接下来将配置文件的bean设置改为如下配置在运行看结果


	


打印的结果是两个bean都变为了多例。这是为什么呢?是由于子类将父类的属性进行继承下来了。当然如果子类定义了对应的属性那么会对父类的属性进行覆盖。

合并BeanDefinition

在spring进行创建bean之前会将bean定义进行合并为RootBeanDefinition。在spring的DefaultListableBeanFactory中也有提现

接下来梳理下这段代码的实现逻辑

protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable 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) {
				// bd.getParentName() == null,表明无父配置,这时直接将当前的 BeanDefinition 升级为 RootBeanDefinition
				if (bd.getParentName() == null) {
					//直接把原始的bean定义升级为RootBeanDefinition
					if (bd instanceof RootBeanDefinition) {
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						//包裹为RootBeanDefinition
						mbd = new RootBeanDefinition(bd);
					}
				}
				//有父定义
				else {
					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);
					}
					// 以父 BeanDefinition 的配置信息为蓝本创建 RootBeanDefinition,也就是“已合并的 BeanDefinition”
					mbd = new RootBeanDefinition(pbd);
					// 用子 BeanDefinition 中的属性覆盖父 BeanDefinition 中的属性
					mbd.overrideFrom(bd);
				}

				// 如果用户未配置 scope 属性,则默认将该属性配置为 singleton
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
				}

				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				//缓存合并后的 BeanDefinition
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}

			return mbd;
		}
	}

梳理流程图如下所示:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/984803.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号