在 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
中去。
这个方法的代码不是特别复杂,大家在了解了其用途之后可以自行下去看下。
希望对您有帮助
QQ
QQ群
微信:TY_3268407924