该方法说明
先说总结作用,该方法的作用就是在xml 文件中通过parent属性与指定的类进行绑定,当调用getMergedLocalBeanDefinition 方法时将parent指定的bean定义对象与当前bean定义对象合并,将合并的对象放入mergedBeanDefinitions这个集合中
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
从名称上来看是合并的bean 定义对象,刚开始看的我一直不明白这个集合的作用,之后我了解到Spring 允许通过配置让一个 Bean 定义继承另一个 Bean 定义。例如我们要配置两个不同的数据库,分别是使用了不同的密码和账号,但是某些属性上是相同的通常我们会有如下配置:
<bean id="dataSource1" class="com.zaxxer.hikari.HikariDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db1"/>
<property name="username" value="user1"/>
<property name="password" value="pass1"/>
<property name="maximumPoolSize" value="20"/>
<property name="minimumIdle" value="5"/>
</bean>
<bean id="dataSource2" class="com.zaxxer.hikari.HikariDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db2"/>
<property name="username" value="user2"/>
<property name="password" value="pass2"/>
<property name="maximumPoolSize" value="20"/>
<property name="minimumIdle" value="5"/>
</bean>
spring 为了简化这个配置允许我们使用parent 属性实现bean定义的继承
<bean id="parentDataSource" class="com.zaxxer.hikari.HikariDataSource" abstract="true">
<property name="maximumPoolSize" value="20"/>
<property name="minimumIdle" value="5"/>
</bean>
<bean id="dataSource1" class="com.zaxxer.hikari.HikariDataSource" parent="parentDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db1"/>
<property name="username" value="user1"/>
<property name="password" value="pass1"/>
</bean>
<bean id="dataSource2" class="com.zaxxer.hikari.HikariDataSource" parent="parentDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db2"/>
<property name="username" value="user2"/>
<property name="password" value="pass2"/>
</bean>
源码讲解
而通过getMergedLocalBeanDefinition 方法将会将这些bean定义的对象合并,具体代码如下,首先尝试从已合并的Bean定义对象集合中获取,如果能获取到直接返回否则尝试合并bean定义对象:
// Quick check on the concurrent map first, with minimal locking.
// 先通过mergedBeanDefinitions获取Bean 对象
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
getMergedBeanDefinition方法首先调用了当前方法的重写方法:
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
首先锁定了bean定义集合对象
synchronized (this.mergedBeanDefinitions)
由于containingBd对象传入的是一个null,所以这段代码忽略掉:
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
主要核心代码在这块,首先判断parentName是否为空:
if (bd.getParentName() == null)
如果为空,表示不需要合并,直接创建一个 RootBeanDefinition对象:
if (bd.getParentName() == null) {
if (bd instanceof RootBeanDefinition rootBeanDef) {
// cloneBeanDefinition方法是new RootBeanDefinition(this)
// 相当于创建了一个根节点对象
mbd = rootBeanDef.cloneBeanDefinition();
} else {
mbd = new RootBeanDefinition(bd);
}
}
否则通过getMergedBeanDefinition(parentBeanName)方法获取parent属性的对象
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
然后覆盖相关属性:
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
mbd = new RootBeanDefinition(pbd);这段代码的具体内容如下,其实就是将parent的bean定义对象的属性覆盖到子bean定义对象当中:
setParentName(original.getParentName());
setBeanClassName(original.getBeanClassName());
setScope(original.getScope());
setAbstract(original.isAbstract());
setFactoryBeanName(original.getFactoryBeanName());
setFactoryMethodName(original.getFactoryMethodName());
setRole(original.getRole());
setSource(original.getSource());
copyAttributesFrom(original);
if (original instanceof AbstractBeanDefinition originalAbd) {
if (originalAbd.hasBeanClass()) {
setBeanClass(originalAbd.getBeanClass());
}
if (originalAbd.hasConstructorArgumentValues()) {
setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
}
if (originalAbd.hasPropertyValues()) {
setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
}
if (originalAbd.hasMethodOverrides()) {
setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
}
Boolean lazyInit = originalAbd.getLazyInit();
if (lazyInit != null) {
setLazyInit(lazyInit);
}
setAutowireMode(originalAbd.getAutowireMode());
setDependencyCheck(originalAbd.getDependencyCheck());
setDependsOn(originalAbd.getDependsOn());
setAutowireCandidate(originalAbd.isAutowireCandidate());
setPrimary(originalAbd.isPrimary());
copyQualifiersFrom(originalAbd);
setInstanceSupplier(originalAbd.getInstanceSupplier());
setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
setInitMethodNames(originalAbd.getInitMethodNames());
setEnforceInitMethod(originalAbd.isEnforceInitMethod());
setDestroyMethodNames(originalAbd.getDestroyMethodNames());
setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod());
setSynthetic(originalAbd.isSynthetic());
setResource(originalAbd.getResource());
最后列出该方法的所有内容:
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.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition rootBeanDef) {
mbd = rootBeanDef.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 {
if (getParentBeanFactory() instanceof ConfigurableBeanFactory parent) {
pbd = parent.getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory 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(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());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}