BeanDefinition 合并

1,335 阅读2分钟

BeanDefinition 的合并

  • 1.BeanDefinition 有父子关系,有个属性叫parentName,通过parentName可以设置BeanDefinition的父子关系
  • 2.为什么要设置BeanDefinition的父子关系,因为子类可以继承父类的属性,抽出共性,跟java的继承有点像
  • 3.BeanDefinition 的合并过程就是将父子关系的 BeanDefinition 属性合并起来,如果有相同的就使用子类的属性值 例子:
  AnnotationConfigApplicationContext applicationContext
               = new AnnotationConfigApplicationContext(springConfiguration.class);
       //父 RootBeanDefinition        
       RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
       rootBeanDefinition.setScope(AbstractBeanDefinition.SCOPE_DEFAULT);
       rootBeanDefinition.getPropertyValues().add("name","xiaoming");
       applicationContext.registerBeanDefinition("parent",rootBeanDefinition);
   
   //子 ChildBeanDefinition ,会继承使用父类已有的属性值,但是如果属性值冲突,不一样
   //那么合并过程中就会使用子类的
       ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("parent");
       childBeanDefinition.setBeanClass(A.class);
       childBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
      

什么时候做合并

在初始化bean工厂的过程中调用: PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors->DefaultListableBeanFactory.getBeanNamesForType

  • DefaultListableBeanFactory.getBeanNamesForType
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
		//....... 
			return doGetBeanNamesForType
            //......
	}
  • DefaultListableBeanFactory#doGetBeanNamesForType
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		List<String> result = new ArrayList<>();

		// 遍历所有的 beanDefinitionNames
		for (String beanName : this.beanDefinitionNames) {
			// Only consider bean as eligible if the bean name
			// is not defined as alias for some other bean.
			if (!isAlias(beanName)) {
				try {
                //获取合并的bd
					RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				//.....
	}
  • AbstractBeanFactory#getMergedLocalBeanDefinition

	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		// 先尝试从缓存获取bd(就是一个map)
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
			return mbd;
		}
        //合并bd
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}
  • AbstractBeanFactory#getMergedBeanDefinition
protected RootBeanDefinition getMergedBeanDefinition(
   		String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
   		throws BeanDefinitionStoreException {

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

   		// 先从缓存拿合并的bd
   		if (containingBd == null) {
   			mbd = this.mergedBeanDefinitions.get(beanName);
   		}
          //合并的bd为空就进行bd合并
   		if (mbd == null) {
           //如果父类为空,就不进行bd合并
   			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 {
   				// 进行bd合并
   				BeanDefinition pbd;
   				try {
   					String parentBeanName = transformedBeanName(bd.getParentName());
   					if (!beanName.equals(parentBeanName)) {
                       //父类的bd可能也需要合并,所以调用 getMergedBeanDefinition
   						pbd = getMergedBeanDefinition(parentBeanName);
   					}
   					else {
   						BeanFactory parent = getParentBeanFactory();
   						if (parent instanceof ConfigurableBeanFactory) {
   							pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
   						}						
   					}
   				}
   				//进行bd合并,子类覆盖父类的,如果子类没有,就用父类的属性
   				mbd = new RootBeanDefinition(pbd);
   				mbd.overrideFrom(bd);
   			}

   			// Set default singleton scope, if not configured before.
   			if (!StringUtils.hasLength(mbd.getScope())) {
   				mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
   			}
   		}

   		return mbd;
   	}
   }