为了账号安全,请及时绑定邮箱和手机立即绑定

spring 中 bean 定义信息合并到底在干什么?

标签:
Java Spring 源码

doGetBean 这个方法中涉及到 getMergedLocalBeanDefinition 这么一个方法,代码如下:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	.....
	
	try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				
				......
					}
					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;
			}		
}

上面只是贴出了其中一段代码。
这个方法如下:

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
	// Quick check on the concurrent map first, with minimal locking.
	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, @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) {
			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 {
				......
			}
			......
		}

		return mbd;
	}
}
	
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
	BeanDefinition bd = this.beanDefinitionMap.get(beanName);
	if (bd == null) {
		if (logger.isTraceEnabled()) {
			logger.trace("No bean named '" + beanName + "' found in " + this);
		}
		throw new NoSuchBeanDefinitionException(beanName);
	}
	return bd;
}
	

上面这段代码大家只是向大家展示了这个方法的大概的调用逻辑,大家先关注 getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) 这个方法中 bd.getParentName() == null 这段代码。这段代码就是这个方法存在的原因。
在 xml 的配置中,bean 的定义有这么一个熟悉 parent。如下:

<?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 中去。

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

希望对您有帮助。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
2
获赞与收藏
0

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消