• Spring IOC源码:obtainFreshBeanFactory 详解(中)


    Spring源码系列:

    Spring IOC源码:简单易懂的Spring IOC 思路介绍
    Spring IOC源码:核心流程介绍
    Spring IOC源码:ApplicationContext刷新前准备工作
    Spring IOC源码:obtainFreshBeanFactory 详解(上)
    Spring IOC源码:obtainFreshBeanFactory 详解(中)
    Spring IOC源码:obtainFreshBeanFactory 详解(下)
    Spring IOC源码:<context:component-scan>源码详解
    Spring IOC源码:invokeBeanFactoryPostProcessors 后置处理器详解
    Spring IOC源码:registerBeanPostProcessors 详解
    Spring IOC源码:实例化前的准备工作
    Spring IOC源码:finishBeanFactoryInitialization详解
    Spring IoC源码:getBean 详解
    Spring IoC源码:createBean( 上)
    Spring IoC源码:createBean( 中)
    Spring IoC源码:createBean( 下)
    Spring IoC源码:finishRefresh 完成刷新详解

    前言

    上篇文章我们介绍了prepareRefresh方法,配置解析前的准备工作,和obtainFreshBeanFactory方法,配置解析核心处理方法。我们讲解到了parseBeanDefinitions方法,该方法会根据命名空间去选择对应的逻辑处理。本章节介绍默认命名空间的处理逻辑parseDefaultElement(ele, delegate);

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    		//判断当前命名空间是否为默认
    		if (delegate.isDefaultNamespace(root)) {
    			NodeList nl = root.getChildNodes();
    			for (int i = 0; i < nl.getLength(); i++) {
    				Node node = nl.item(i);
    				if (node instanceof Element) {
    					Element ele = (Element) node;
    					if (delegate.isDefaultNamespace(ele)) {
    						//默认命名空间节点的处理,例如: 
    						parseDefaultElement(ele, delegate);
    					}
    					else {
    						// 自定义命名空间节点的处理,例如:
    						delegate.parseCustomElement(ele);
    					}
    				}
    			}
    		}
    		else {
    			//非默认命名空间走其它逻辑
    			delegate.parseCustomElement(root);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    正文

    进入parseDefaultElement(ele, delegate)方法,我们可以看到有四种类型的判断,import、alias、bean、beans。这里获取一级节点,判断节点类型选择对应的解析方法。几种类型的解析都是比较类似的,这里我们使用的bean,学会的bean去看其它都是大同小异,而beans节点其实是重新调用一遍doRegisterBeanDefinitions方法,进行子节点的遍历解析工作。bean节点解析见方法1

    	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    		//解析import
    		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
    			importBeanDefinitionResource(ele);
    		}
    		//解析alias
    		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
    			processAliasRegistration(ele);
    		}
    		//解析bean
    		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
    			processBeanDefinition(ele, delegate);
    		}
    		//解析beans
    		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
    			// recurse
    			doRegisterBeanDefinitions(ele);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    xml配置如下:

    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	   xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<bean name="teacher" class="service.impl.Teacher">
    		<property name="name" value="张三">property>
    		<property name="age" value="30">property>
    	bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    方法1:processBeanDefinition

    	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    		//通过解析器进行解析,解析出类名、class、id、父类、属性依赖等
    		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    		if (bdHolder != null) {
    			//bean解析器只能解析一些默认的配置,这里判断是否有自定义的属性或子节点需要进一步解析并封装,
    			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    			try {
    				// 将bdHolder 注册到上下文缓存中beanDefinitionNames、beanDefinitionMap、aliasMap
    				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    			}
    			catch (BeanDefinitionStoreException ex) {
    				getReaderContext().error("Failed to register bean definition with name '" +
    						bdHolder.getBeanName() + "'", ele, ex);
    			}
    			// Send registration event.
    			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    1、delegate.parseBeanDefinitionElement(ele)方法:见方法2详解

    2、delegate.decorateBeanDefinitionIfRequired(ele, bdHolder)方法:
    这个方法主要是考虑到bean节点中的属性或者子节点包含了自定义内容,默认的解析器没办法解析到,所以需要做下后置处理,判断是否有自定义的,通过自定义获取命名空间,通过命名空间加载解析器进行处理,将处理好的值封装到步骤1解析出来的BeanDefinitionHolder 中。例如下面的“zhudachang”属性和 < myBean > 子节点。这节我们要研究默认命名空间,所以这里不做深入,等后面讲解了自定义的内容后,再来看这块就比较简单了。

    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	   xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<bean name="teacher" class="service.impl.Teacher" zhudachang="">
    		<property name="name" value="张三">property>
    		<property name="age" value="30">property>
    		<myBean>myBean>
    	bean>
    
    beans>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    方法2:parseBeanDefinitionElement

    	
    	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    		return parseBeanDefinitionElement(ele, null);
    	}
    
    
    	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    		//获取id和name属性值
    		String id = ele.getAttribute(ID_ATTRIBUTE);
    		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    		//对name属性值匹配“,;”切割看是否有多个名称,加入别名缓存
    		List<String> aliases = new ArrayList<>();
    		if (StringUtils.hasLength(nameAttr)) {
    			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    			aliases.addAll(Arrays.asList(nameArr));
    		}
    		//如果beanName为空,则以aliases中的第一条数据作为beanName名称,并移除。
    		String beanName = id;
    		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
    			beanName = aliases.remove(0);
    			if (logger.isTraceEnabled()) {
    				logger.trace("No XML 'id' specified - using '" + beanName +
    						"' as bean name and " + aliases + " as aliases");
    			}
    		}
    		//查询一下该beanName 名称是否作为第一个被使用了
    		if (containingBean == null) {
    			checkNameUniqueness(beanName, aliases, ele);
    		}
    		//解析节点并封装成GenericBeanDefinition
    		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    		if (beanDefinition != null) {
    			if (!StringUtils.hasText(beanName)) {
    				try {
    					if (containingBean != null) {
    						//默认规则生成,获取class名称,如果class名称为空,则看beanDefinition的父类或FactoryBean的名称+固定后最作为Bean名称,如果是内部的Bean则按另一个逻辑生成;
    						beanName = BeanDefinitionReaderUtils.generateBeanName(
    								beanDefinition, this.readerContext.getRegistry(), true);
    					}
    					else {
    						beanName = this.readerContext.generateBeanName(beanDefinition);
    						// Register an alias for the plain bean class name, if still possible,
    						// if the generator returned the class name plus a suffix.
    						// This is expected for Spring 1.2/2.0 backwards compatibility.
    						String beanClassName = beanDefinition.getBeanClassName();
    						//如果是默认规则生成的,则加入别名集合中
    						if (beanClassName != null &&
    								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
    								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
    							aliases.add(beanClassName);
    						}
    					}
    					if (logger.isTraceEnabled()) {
    						logger.trace("Neither XML 'id' nor 'name' specified - " +
    								"using generated bean name [" + beanName + "]");
    					}
    				}
    				catch (Exception ex) {
    					error(ex.getMessage(), ele);
    					return null;
    				}
    			}
    			String[] aliasesArray = StringUtils.toStringArray(aliases);
    			//将beanDefinition跟类名、别名封装成 BeanDefinitionHolder
    			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    		}
    
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    1、beanName的获取规则,如果bean节点配置了id属性,则以id作为beanName。如果没有id,但是有配置name属性,则解析名称中是否含有多个,如果有多个则将第一个作为beanName,其余的作为别名,加入aliases集合中。
    例如:

    	<bean name="ZHU,DA,CHANG" class="service.impl.Teacher">
    		<property name="name" value="张三">property>
    		<property name="age" value="30">property>
    	bean>
    
    • 1
    • 2
    • 3
    • 4

    这里的beanName为"ZHU",别名为“DA”,“CHANG"

    	<bean id="teacher" name="zhudachang" class="service.impl.Teacher">
    		<property name="name" value="张三">property>
    		<property name="age" value="30">property>
    	bean>
    
    • 1
    • 2
    • 3
    • 4

    这里的beanName为"teacher",别名为“zhudachang”

    2、parseBeanDefinitionElement(ele, beanName, containingBean)方法:见方法3详解

    方法3:parseBeanDefinitionElement

    	public AbstractBeanDefinition parseBeanDefinitionElement(
    			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    		//将beanName封装成BeanEntry对象
    		this.parseState.push(new BeanEntry(beanName));
    		//获取class类属性
    		String className = null;
    		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
    			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    		}
    		//获取父类属性
    		String parent = null;
    		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
    			parent = ele.getAttribute(PARENT_ATTRIBUTE);
    		}
    
    		try {
    			//创建GenericBeanDefinition,并设置父类名称,通过className获取class并设置
    			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    			//解析设置各种属性
    			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    			//设置description信息
    			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    			//解析元数据
    			parseMetaElements(ele, bd);
    			//设置LookupOverride
    			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    			//设置ReplacedMethod
    			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    			//解析设置构造函数节点
    			parseConstructorArgElements(ele, bd);
    			//解析设置子节点属性
    			parsePropertyElements(ele, bd);
    			//解析设置Qualifier
    			parseQualifierElements(ele, bd);
    
    			bd.setResource(this.readerContext.getResource());
    			bd.setSource(extractSource(ele));
    
    			return bd;
    		}
    		catch (ClassNotFoundException ex) {
    			error("Bean class [" + className + "] not found", ele, ex);
    		}
    		catch (NoClassDefFoundError err) {
    			error("Class that bean class [" + className + "] depends on not found", ele, err);
    		}
    		catch (Throwable ex) {
    			error("Unexpected failure during bean definition parsing", ele, ex);
    		}
    		finally {
    			this.parseState.pop();
    		}
    
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    1、parseBeanDefinitionAttributes(ele, beanName, containingBean, bd)方法,见方法4详解
    2、parseLookupOverrideSubElements(ele, bd.getMethodOverrides())
    该方法主要解析子节点中的< lookup-method >标签,该标签处理Bean中属性为原型模式,也就是每次获取该属性时都会新创建一个对象。
    如:Teacher类中声明了Address属性,而我们的Address是prototype原型模式,也就是每次获取该值都会创建一个新的对象,而Teacher是一个单例,获取该类时,每次都从缓存中获取,导致类中的Adress也是一个单例,这里就是为后续处理该问题作准备。后续文章会专门讲解这个的用法。

    	<bean name="address" class="service.Address" scope="prototype">bean>
    	<bean id="teacher" name="teacher" class="service.impl.Teacher" >
    		<lookup-method name="getAddress" bean="address">lookup-method>
    	bean>
    
    • 1
    • 2
    • 3
    • 4

    3、parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

    	<bean name="address" class="service.Address" scope="prototype">bean>
    	<bean id="teacher" name="teacher" class="service.impl.Teacher" >
    		<replaced-method name="getAddress" replacer="addressMethodReplacer">replaced-method>
    	bean>
    
    • 1
    • 2
    • 3
    • 4

    4、parseConstructorArgElements(ele, bd)方法,见方法5详解

    5、parsePropertyElements(ele, bd)方法见方法9详解

    方法4:parseBeanDefinitionAttributes

        // 解析设置singleton属性
        if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
            // singleton属性以被scope属性代替
            error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
        }
        // 解析设置scope属性
        else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
            bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
        }
        else if (containingBean != null) {
            // Take default from containing bean in case of an inner bean definition.
            bd.setScope(containingBean.getScope());
        }
     
        // 解析设置abstract属性
        if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
            bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
        }
     
        // 解析设置lazy-init属性, 默认为false
        String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
        if (DEFAULT_VALUE.equals(lazyInit)) {
            lazyInit = this.defaults.getLazyInit();
        }
        bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
     
        // 解析设置autowire属性
        String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
        bd.setAutowireMode(getAutowireMode(autowire));
     
        // 解析设置dependency-check属性
        String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
        bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
     
        // 解析设置depends-on属性
        if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
            String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
            bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
        }
     
        // 解析设置autowire-candidate属性
        String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
        if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
            String candidatePattern = this.defaults.getAutowireCandidates();
            if (candidatePattern != null) {
                String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
                bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
            }
        }
        else {
            bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
        }
     
        // 解析设置primary属性
        if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
            bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
        }
     
        // 解析设置init-method属性
        if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
            String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
            if (!"".equals(initMethodName)) {
                bd.setInitMethodName(initMethodName);
            }
        }
        else {
            if (this.defaults.getInitMethod() != null) {
                bd.setInitMethodName(this.defaults.getInitMethod());
                bd.setEnforceInitMethod(false);
            }
        }
     
        // 解析设置destroy-method属性
        if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
            String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
            bd.setDestroyMethodName(destroyMethodName);
        }
        else {
            if (this.defaults.getDestroyMethod() != null) {
                bd.setDestroyMethodName(this.defaults.getDestroyMethod());
                bd.setEnforceDestroyMethod(false);
            }
        }
     
        // 解析设置factory-method属性
        if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
            bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
        }
        // 解析factory-bean属性
        if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
            bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
        }
     
        return bd;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    方法5:parseConstructorArgElements

    		NodeList nl = beanEle.getChildNodes();
    		for (int i = 0; i < nl.getLength(); i++) {
    			Node node = nl.item(i);
    			if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
    				parseConstructorArgElement((Element) node, bd);
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里遍历子节点中的< constructor-arg >标签,对其属性进行解析封装,parseConstructorArgElement((Element) node, bd)方法见方法6详解

    	<bean id="address"  class="service.Address" >bean>
    
    	<bean  id="teacher" name="teacher" class="service.impl.Teacher">
    		<constructor-arg index="0" value="zhangsan">constructor-arg>
    		<constructor-arg index="1" value="13">constructor-arg>
    		<constructor-arg index="2" ref="address">constructor-arg>
    		<constructor-arg index="3" >
    			<list>
    				<value>zhudachang1value>
    				<value>zhudachang2value>
    				<value>zhudachang3value>
    			list>
    		constructor-arg>
    	bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    方法6:parseConstructorArgElement

    public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
    		//获取index属性
    		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
    		//获取type属性
    		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
    		//获取name属性
    		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    		if (StringUtils.hasLength(indexAttr)) {
    			//如果有index属性
    			try {
    				int index = Integer.parseInt(indexAttr);
    				if (index < 0) {
    					error("'index' cannot be lower than 0", ele);
    				}
    				else {
    					try {
    						//校验该index是否>=0,否则抛异常
    						this.parseState.push(new ConstructorArgumentEntry(index));
    						//获取其值,可能是通过 value 属性、ref 属性、list 属性等
    						Object value = parsePropertyValue(ele, bd, null);
    						//封装成ConstructorArgumentValues对象
    						ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
    						if (StringUtils.hasLength(typeAttr)) {
    						//设置type值
    							valueHolder.setType(typeAttr);
    						}
    						if (StringUtils.hasLength(nameAttr)) {
    						//设置name值
    							valueHolder.setName(nameAttr);
    						}
    						valueHolder.setSource(extractSource(ele));
    						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
    							error("Ambiguous constructor-arg entries for index " + index, ele);
    						}
    						else {
    							//添加下标及其对应的值
    							bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
    						}
    					}
    					finally {
    						this.parseState.pop();
    					}
    				}
    			}
    			catch (NumberFormatException ex) {
    				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
    			}
    		}
    		else {
    			try {
    				//如果没有index,此时不做校验
    				this.parseState.push(new ConstructorArgumentEntry());
    				//获取当前设置值,可能是通过 value 属性、ref 属性、list 属性等
    				Object value = parsePropertyValue(ele, bd, null);
    				//同上面步骤一样
    				ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
    				if (StringUtils.hasLength(typeAttr)) {
    					valueHolder.setType(typeAttr);
    				}
    				if (StringUtils.hasLength(nameAttr)) {
    					valueHolder.setName(nameAttr);
    				}
    				valueHolder.setSource(extractSource(ele));
    				//由于没有下标,这里直接添加集合中
    				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
    			}
    			finally {
    				this.parseState.pop();
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    parsePropertyValue(ele, bd, null)方法,会解析出当前节点对应的引用类型值,见方法7详解

    方法7:parsePropertyValue

    public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
    		String elementName = (propertyName != null ?
    				" element for property '" + propertyName + "'" :
    				" element");
    		//获取该节点下的子节点
    		NodeList nl = ele.getChildNodes();
    		Element subElement = null;
    		//如果是List类型,则有子节点。这里会对子节点进行校验
    		for (int i = 0; i < nl.getLength(); i++) {
    			Node node = nl.item(i);
    			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
    					!nodeNameEquals(node, META_ELEMENT)) {
    				// Child element is what we're looking for.
    				if (subElement != null) {
    					error(elementName + " must not contain more than one sub-element", ele);
    				}
    				else {
    					subElement = (Element) node;
    				}
    			}
    		}
    		//判断是否有该属性
    		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
    		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
    		//这里不允许有value跟ref共存或者跟有子节点的共存 如list
    		if ((hasRefAttribute && hasValueAttribute) ||
    				((hasRefAttribute || hasValueAttribute) && subElement != null)) {
    			error(elementName +
    					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
    		}
    		//
    		if (hasRefAttribute) {
    			//获取属性值并将该属性值封装成RuntimeBeanReference 对象
    			String refName = ele.getAttribute(REF_ATTRIBUTE);
    			if (!StringUtils.hasText(refName)) {
    				error(elementName + " contains empty 'ref' attribute", ele);
    			}
    			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
    			ref.setSource(extractSource(ele));
    			return ref;
    		}
    		else if (hasValueAttribute) {
    			//如果有value值,则封装成TypedStringValue 
    			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
    			valueHolder.setSource(extractSource(ele));
    			return valueHolder;
    		}
    		else if (subElement != null) {
    			//如果有子节点,对子节点内容进行解析
    			return parsePropertySubElement(subElement, bd);
    		}
    		else {
    			// Neither child element nor "ref" or "value" attribute found.
    			error(elementName + " must specify a ref or value", ele);
    			return null;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    parsePropertySubElement(subElement, bd)方法对子节点进行解析,见方法8详解

    方法8:parsePropertySubElement

    public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
    		//判断节点标签是否是默认命名空间,不是则走自定义逻辑
    		if (!isDefaultNamespace(ele)) {
    			return parseNestedCustomElement(ele, bd);
    		}
    		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
    			//如果是Bean标签,则进行解析,并封装成BeanDefinitionHolder 
    			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
    			if (nestedBd != null) {
    				//判断该节点是否有自定义标签,有则调用自定义逻辑处理,补充新的解析内容进来
    				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
    			}
    			return nestedBd;
    		}
    		else if (nodeNameEquals(ele, REF_ELEMENT)) {
    			// 如果是ref,引用其它Bean,获取引用的beanName名称
    			String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
    			boolean toParent = false;
    			if (!StringUtils.hasLength(refName)) {
    				// 获取父类beanName
    				refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
    				toParent = true;
    				if (!StringUtils.hasLength(refName)) {
    					error("'bean' or 'parent' is required for  element", ele);
    					return null;
    				}
    			}
    			if (!StringUtils.hasText(refName)) {
    				error(" element contains empty target attribute", ele);
    				return null;
    			}
    			//封装成RuntimeBeanReference 
    			RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
    			ref.setSource(extractSource(ele));
    			return ref;
    		}
    		//解析idref节点
    		else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
    			return parseIdRefElement(ele);
    		}
    		//解析value
    		else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
    			return parseValueElement(ele, defaultValueType);
    		}
    		//解析null
    		else if (nodeNameEquals(ele, NULL_ELEMENT)) {
    			// It's a distinguished null value. Let's wrap it in a TypedStringValue
    			// object in order to preserve the source location.
    			TypedStringValue nullHolder = new TypedStringValue(null);
    			nullHolder.setSource(extractSource(ele));
    			return nullHolder;
    		}
    		//解析Array数组
    		else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
    			return parseArrayElement(ele, bd);
    		}
    		//解析List集合
    		else if (nodeNameEquals(ele, LIST_ELEMENT)) {
    			return parseListElement(ele, bd);
    		}
    		//解析Set集合
    		else if (nodeNameEquals(ele, SET_ELEMENT)) {
    			return parseSetElement(ele, bd);
    		}
    		//解析Map集合
    		else if (nodeNameEquals(ele, MAP_ELEMENT)) {
    			return parseMapElement(ele, bd);
    		}
    		//解析props
    		else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
    			return parsePropsElement(ele);
    		}
    		else {
    			error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
    			return null;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    1、list节点的解析,获取该节点下的子节点,遍历调用parsePropertySubElement,并将每个子节点添加至Collection中。
    2、其它集合Map、Set、Array等的解析过程也跟list类似。

    方法9:parsePropertyElements

    以上我们介绍了< constructor-arg >标签的解析过程,下面来看下

    	public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    		NodeList nl = beanEle.getChildNodes();
    		for (int i = 0; i < nl.getLength(); i++) {
    			Node node = nl.item(i);
    			//如果是默认命名空间标签且是property属性的话,进行解析
    			if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
    				parsePropertyElement((Element) node, bd);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public void parsePropertyElement(Element ele, BeanDefinition bd) {
    		//获取name属性值
    		String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
    		if (!StringUtils.hasLength(propertyName)) {
    			error("Tag 'property' must have a 'name' attribute", ele);
    			return;
    		}
    		//校验该值不为空
    		this.parseState.push(new PropertyEntry(propertyName));
    		try {
    			if (bd.getPropertyValues().contains(propertyName)) {
    				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
    				return;
    			}
    			//解析获取其值,该方法在前面的解析中有讲解过,这里不做讲解
    			Object val = parsePropertyValue(ele, bd, propertyName);
    			//根据名称、对象值封装成PropertyValue 
    			PropertyValue pv = new PropertyValue(propertyName, val);
    			parseMetaElements(ele, pv);
    			pv.setSource(extractSource(ele));
    			bd.getPropertyValues().addPropertyValue(pv);
    		}
    		finally {
    			this.parseState.pop();
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    xml配置案例如下:

    	<bean id="address"  class="service.Address" scope="prototype">bean>
    	<bean id="teacher" class="service.impl.Teacher">
    		<property name="name" value="zhudachang">property>
    		<property name="age" value="11">property>
    		<property name="address" ref="address">property>
    	bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    到这里我们的解析工作就完成了,下面回到方法1中,解析后需要将BeanDefinition注册到上下文缓存中,见方法10详解

    方法10:registerBeanDefinition

    	public static void registerBeanDefinition(
    			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    			throws BeanDefinitionStoreException {
    
    		// 获取beanName名称
    		String beanName = definitionHolder.getBeanName();
    		//注册到缓存中
    		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
    		//获取别名集合,注册到上下文的别名缓存中
    		String[] aliases = definitionHolder.getAliases();
    		if (aliases != null) {
    			for (String alias : aliases) {
    				registry.registerAlias(beanName, alias);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1、我们看到传进来的是BeanDefinitionRegistry 注册器,我们可以把它当成管理上下文的工具类吧,使用它可以操作上下文的部分增删改查工作
    2、registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())方法,见方法11详解
    3、registry.registerAlias(beanName, alias)方法,见方法13详解

    方法11:registerBeanDefinition

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    			throws BeanDefinitionStoreException {
    		//做下校验
    		Assert.hasText(beanName, "Bean name must not be empty");
    		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    		//如果是AbstractBeanDefinition,则校验
    		if (beanDefinition instanceof AbstractBeanDefinition) {
    			try {
    				((AbstractBeanDefinition) beanDefinition).validate();
    			}
    			catch (BeanDefinitionValidationException ex) {
    				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    						"Validation of bean definition failed", ex);
    			}
    		}
    		//判断缓存中是否存在了该beanName的BeanDefinition 
    		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    		if (existingDefinition != null) {
    			if (!isAllowBeanDefinitionOverriding()) {
    				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
    			}
    			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
    				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    				if (logger.isInfoEnabled()) {
    					logger.info("Overriding user-defined bean definition for bean '" + beanName +
    							"' with a framework-generated bean definition: replacing [" +
    							existingDefinition + "] with [" + beanDefinition + "]");
    				}
    			}
    			else if (!beanDefinition.equals(existingDefinition)) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Overriding bean definition for bean '" + beanName +
    							"' with a different definition: replacing [" + existingDefinition +
    							"] with [" + beanDefinition + "]");
    				}
    			}
    			else {
    				if (logger.isTraceEnabled()) {
    					logger.trace("Overriding bean definition for bean '" + beanName +
    							"' with an equivalent definition: replacing [" + existingDefinition +
    							"] with [" + beanDefinition + "]");
    				}
    			}
    			//加入缓存中,进行覆盖
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    		}
    		else {
    			//检查下当前bean工厂是否开始创建工作,这里是为了加锁
    			if (hasBeanCreationStarted()) {
    				// Cannot modify startup-time collection elements anymore (for stable iteration)
    				synchronized (this.beanDefinitionMap) {
    					//将当前beanDefinition放入缓存中
    					this.beanDefinitionMap.put(beanName, beanDefinition);
    					//统计下数量
    					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
    					updatedDefinitions.addAll(this.beanDefinitionNames);
    					updatedDefinitions.add(beanName);
    					this.beanDefinitionNames = updatedDefinitions;
    					removeManualSingletonName(beanName);
    				}
    			}
    			else {
    				// 将当前beanDefinition放入缓存中
    				this.beanDefinitionMap.put(beanName, beanDefinition);
    				//将beanName加入缓存中
    				this.beanDefinitionNames.add(beanName);
    				removeManualSingletonName(beanName);
    			}
    			this.frozenBeanDefinitionNames = null;
    		}
    		//如果Bean存在于缓存中,并且的单例的,这里需要重置
    		if (existingDefinition != null || containsSingleton(beanName)) {
    			resetBeanDefinition(beanName);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    1、((AbstractBeanDefinition) beanDefinition).validate();
    该方法用于校验节点中不能同时存在factory-method属性和子节点< lookup-method >、< replaced-method >。这个if语句是为了确保,上述两者不能共存,否则就会报错。这是因为,如果给一个 Bean 配置了工厂方法,那么它会由工厂方法来创建,而不是 Spring 默认的方式创建,这种情况下无法进行方法的覆盖。因此,这里的判断是为了确保配置信息没有出现冲突。

    	public void validate() throws BeanDefinitionValidationException {
    		if (hasMethodOverrides() && getFactoryMethodName() != null) {
    			throw new BeanDefinitionValidationException(
    					"Cannot combine factory method with container-generated method overrides: " +
    					"the factory method must create the concrete bean instance.");
    		}
    		if (hasBeanClass()) {
    			prepareMethodOverrides();
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、resetBeanDefinition(beanName)方法,见方法12详解

    方法12:resetBeanDefinition

    protected void resetBeanDefinition(String beanName) {
    		// 从合并的MergedBeanDefinition缓存中移除
    		clearMergedBeanDefinition(beanName);
    		//这里移除了很多处缓存,如IOC三级缓存等
    		destroySingleton(beanName);
    
    		// 通知后置处理器进行重置处理
    		for (BeanPostProcessor processor : getBeanPostProcessors()) {
    			if (processor instanceof MergedBeanDefinitionPostProcessor) {
    				((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
    			}
    		}
    
    		
    		for (String bdName : this.beanDefinitionNames) {
    			if (!beanName.equals(bdName)) {
    				BeanDefinition bd = this.beanDefinitionMap.get(bdName);
    				//当前遍历的BeanDefinition的parentName为beanName,则递归调用resetBeanDefinition进行重置
    				if (bd != null && beanName.equals(bd.getParentName())) {
    					resetBeanDefinition(bdName);
    				}
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    方法13:resetBeanDefinition

    public void registerAlias(String name, String alias) {
    		Assert.hasText(name, "'name' must not be empty");
    		Assert.hasText(alias, "'alias' must not be empty");
    		synchronized (this.aliasMap) {
    			//如果别名缓存中已经存在该数据,则移除
    			if (alias.equals(name)) {
    				this.aliasMap.remove(alias);
    				if (logger.isDebugEnabled()) {
    					logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
    				}
    			}
    			else {
    				String registeredName = this.aliasMap.get(alias);
    				if (registeredName != null) {
    					//如果别名已经注册过,直接返回
    					if (registeredName.equals(name)) {
    						// An existing alias - no need to re-register
    						return;
    					}
    					if (!allowAliasOverriding()) {
    						throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
    								name + "': It is already registered for name '" + registeredName + "'.");
    					}
    					if (logger.isDebugEnabled()) {
    						logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
    								registeredName + "' with new target name '" + name + "'");
    					}
    				}
    				//检查name和alias是否存在循环引用。例如A的别名为B,B的别名为A
    				checkForAliasCircle(name, alias);
    				//加入缓存
    				this.aliasMap.put(alias, name);
    				if (logger.isTraceEnabled()) {
    					logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
    				}
    			}
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    总结

    至此,Spring 加载默认命名空间的 BeanDefinition 的过程就全部分析完了,可以说这是 BeanFactory 实例化前最复杂的逻辑了。我们梳理一下流程:
    1、Spring判断是否默认命名空间,加载默认解析器进行解析
    2、使用默认命名空间解析完成后得到初步的BeanDefinition对象,再调用自定义命名空间进行处理判断是否需要补充处理。
    3、将解析的BeanDefinition 加入beanDefinitionMap缓存中,将beanName加入beanDefinitionNames缓存中,将aliases加入到aliasMap缓存中。
    后面我们会继续讲解自定义命名空间的处理过程。

  • 相关阅读:
    软件工程基础实验二
    CV:阿里在CV数据增强领域带来SOTA新范式(已被NeurIPS2022接收)—基于离散化对抗训练的鲁棒视觉新基准!
    代码文档
    LeetCode 0146. LRU 缓存:双向链表 + 哈希
    数据结构之<二叉搜索树>
    基础讲解——ES6
    Linux下“多线程”相关内容整理总结
    数据获取 | 如何获取各地高质量的航拍图并生成等高线地形?
    【刷题笔记9.24】LeetCode:对称二叉树
    为什么不应该在 Flutter 中使用全局变量
  • 原文地址:https://blog.csdn.net/weixin_45031612/article/details/127739593