spring框架2 - 默认标签解析

    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)) {
                        this.parseDefaultElement(ele, delegate);  // 解析默认标签
                    } else {
                        delegate.parseCustomElement(ele);  // 解析自定义标签
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);  // 解析自定义标签
        }
    }

默认标签:import、alias、bean、beans四种标签的解析

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, "bean")) {
            this.processBeanDefinition(ele, delegate);
        } else if (delegate.nodeNameEquals(ele, "beans")) {
            this.doRegisterBeanDefinitions(ele);
        }
    }

bean标签:(很重要)

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // step1:元素解析
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            // step2:如果子节点下还有自定义标签,则对其进行解析
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
                // step3:对bdHoldr进行注册
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                BeanDefinitionStoreException ex = var5;
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
            }
            // step4:发送注册事件
            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

bean标签的解析和注册的时序图如下所示:

step1:parseBeanDefinitionElement:

在parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)方法中, 其实一共执行了如下4个步骤:

① 提取Element元素中的“id”和“name”属性,并将name解析为aliases,然后为 beanName赋值。

② 解析其他属性并封装到GenericBeanDefinition类型的实例中。

③ 如果发现bean没有指定beanName,那么使用默认规则生成beanName。

④ 将获取到的信息封装到BeanDefinitionHolder类型的实例中。

举例:bean.xml中的一个bean

    <!-- bean 标签演示 -->
    <bean id="m416" class="com.muse.springdemo.entity.Gun">
        <property name="name" value="M416"/>
        <property name="bulletNums" value="45"/>
        <property name="desc" value="非常好用的一把枪"/>
    </bean>

关于BeanDefinitionParserDelegate类parseBeanDefinitionElement方法的源码部分,如下页所示:

	/**
	 * 解析提供的<bean>元素。如果在解析期间发生错误,可能返回null。错误被报告给org.springframework.beans.factory.parse.problemreporter
	 */
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
		return parseBeanDefinitionElement(ele, null);
	}

	/**
	 * 解析提供的<bean>元素。如果在解析期间发生错误,可能返回null。错误被报告给org.springframework.beans.factory.parse.problemreporter
	 */
	// eg1:containingBean=null
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		String id = ele.getAttribute(ID_ATTRIBUTE); 		// eg1: id="m416"
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // eg1: name=""

		/** 1: 将配置中的"name"属性,解析为aliases */
		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) { // eg1:nameAttr=""
			// 例如:nameAttr="made,in;china",delimiters=",; ",返回数组:[made, in, china]
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); // ",; "
			aliases.addAll(Arrays.asList(nameArr));
		}

		/** 2: 如果配置中没有指定"id"属性,并且aliases不为空,则取aliases列表中的第一个名称作为beanName */
		String beanName = id; // eg1: beanName="m416"
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) // eg1:aliases.size()=0
			beanName = aliases.remove(0);

		/** 3: 校验beanName和aliases是否被使用过 */
		if (containingBean == null) // eg1: containingBean=null
			checkNameUniqueness(beanName, aliases, ele);

		/** 4: 解析配置文件中其它的属性,并封装为GenericBeanDefinition实例 */
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) { // eg1:beanName="m416"
				try {
					if (containingBean != null)
						beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
				}
				catch (Exception ex) {
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases); // eg1:aliases.size()=0
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); // eg1:beanName="m416",aliasesArray=[]
		}

		return null;
	}

checkNameUniqueness(String beanName, List<String> aliases, Element beanElement):

	/**
	 * 验证指定的beanName和aliases是否已经在当前级别的bean元素嵌套中使用。
	 */
	// eg1: beanName="m416", aliases.size()=0
	protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
		String foundName = null;

		/** 1: 如果beanName已经被使用过,则将beanName赋值给foundName变量 */
		if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) // eg1: usedNames.size()=0
			foundName = beanName;

		/** 2: 如果aliases中存在已经被使用过的名称,则将aliase中第一个校验出已经被使用过的名称复制给foundName */
		if (foundName == null) // eg1: foundName=null
			foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases); // eg1: usedNames.size()=0,aliases.size()=0

		/** 3: 如果foundName不为null,则表明存在被使用过的beanName或aliase,抛出异常即可 */
		if (foundName != null) // eg1: foundName=null
			error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);

		this.usedNames.add(beanName); // eg1: beanName="m416"
		this.usedNames.addAll(aliases); // eg1: aliases.size()=0, usedNames=["m416"]
	}

	/**
	 * 解析bean定义本身,而不考虑名称或别名。如果在解析bean定义期间发生问题,可能返回null。
	 */
	// eg1:containingBean=null,beanName="m416"
	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
		this.parseState.push(new BeanEntry(beanName));

		/** 1:尝试获得"class"属性 */
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) // eg1:true
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); // eg1:className="com.muse.springdemo.entity.Gun"

		/** 2:尝试获得"parent"属性 */
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) // eg1:false
			parent = ele.getAttribute(PARENT_ATTRIBUTE);

		try {
			/** 3:创建GenericBeanDefinition实例对象 */
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			/**
			 * 4:解析默认bean的各个属性(其中解析内容包括:singleton属性、scope属性、abstract属性、lazy-init属性、autowire属性、
			 * depends-on属性、autowire-candidate属性、primary属性、init-method属性、destroy-method属性、factory-method属性、factory-bean属性)
			 */
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); // eg1:null,"description"

			/** 5:解析元数据 */
			parseMetaElements(ele, bd);

			/** 6:解析lookup-method属性 */
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

			/** 7:解析replaced-method属性 */
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			/** 8:解析构造函数参数 */
			parseConstructorArgElements(ele, bd);

			/** 9:解析property子元素 */
			parsePropertyElements(ele, bd);

			/** 10:解析qualifier子元素 */
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));
			return bd;    // 返回组装好的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;
	}

/** 3:创建GenericBeanDefinition实例对象 */

创建BeanDefinition的这部分内容,是通过调用createBeanDefinition方法实现的。但是, 在介绍整个方法内部逻辑之前,我们先来了解一下BeanDefinition,它到底是做什么用的? BeanDefinition是配置文件中元素标签在Spring容器中的表现形式,也就是说,它 是用来承载bean信息的。在配置文件中可以定义父级和子集,它们分别由 RootBeanDefinition和ChildBeanDefinition表示。而如果没有父级的话,则用 RootBeanDefinition表示。而GenericBeanDefinition是从2.5版本之后加入进来的,用于为 bean文件配置属性属性定义提供一站式服务  

	/**
	 * 为给定的类名和父类名创建一个bean定义。
	 */
	// eg1: className="com.muse.springdemo.entity.Gun", parentName=null
	protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) throws ClassNotFoundException {
		return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
	}

//为给定的父类名创建一个新的GenericBeanDefinition,如果指定了类加载器,则立即加载bean类
// eg1:className="com.muse.springdemo.entity.Gun" parentName=null, classLoader=null
    public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
        GenericBeanDefinition bd = new GenericBeanDefinition();
        bd.setParentName(parentName);  // parentName=null
        if (className != null) {    // eg1:className="com.muse.springdemo.entity.Gun"
            if (classLoader != null) {   // classLoader=null
                bd.setBeanClass(ClassUtils.forName(className, classLoader));
            } else {
                bd.setBeanClassName(className);   // eg1:className="com.muse.springdemo.entity.Gun"
            }
        }
        return bd;
    }

/* 4:解析默认bean的各个属性 */

parseBeanDefinitionAttributes(ele, beanName, containingBean, bd)  bean属性的解析: 

在parseBeanDefinitionAttributes方法中,通过解析配置中的bean信息,并将其赋值给 AbstractBeanDefinition实例对象。其中解析内容包括:singleton属性、scope属性、abstract属性、lazy-init属性、autowire属性、 * depends-on属性、autowire-candidate属性、primary属性、init-method属性、destroy-method属性、factory-method属性、factory-bean属性

	public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

		/** 1:向bd中设置scope变量的值 */
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE))  // eg1:false,判断是否存在"singleton"属性
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) // eg1:false,判断是否存在"scope"属性
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		else if (containingBean != null) // eg1:containingBean=null
			bd.setScope(containingBean.getScope());

		/** 2:向bd中设置abstractFlag变量的值 */
		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) // eg1:false,判断是否存在"abstract"属性
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));

		/** 3:向bd中设置lazyInit变量的值 */
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); // eg1:lazyInit="default"
		if (isDefaultValue(lazyInit))
			lazyInit = this.defaults.getLazyInit();	// eg1:lazyInit="false"
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

		/** 4:向bd中设置autowireMode变量的值 */
		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); // eg1:autowire="default"
		bd.setAutowireMode(getAutowireMode(autowire)); // eg1:getAutowireMode(autowire)=AUTOWIRE_NO  默认为0

		/** 5:向bd中设置dependsOn变量的值 */
		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { // eg1:false,判断是否存在"depends-on"属性
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); // ",; "
		}

		/** 6:向bd中设置autowireCandidate变量的值 */
		String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); // eg1:autowireCandidate="default,获得"autowire-candidate"属性
		if (isDefaultValue(autowireCandidate)) {
			String candidatePattern = this.defaults.getAutowireCandidates(); // 默认值为null
			if (candidatePattern != null) { // eg1: candidatePattern=null
				String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
				bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
			}
		} else bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));

		/** 7:向bd中设置primary变量的值 */
		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) // eg1:false,判断是否存在"primary"属性
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));

		/** 8:向bd中设置initMethodName和enforceInitMethod变量的值 */
		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { // eg1:false,判断是否存在"init-method"属性
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			bd.setInitMethodName(initMethodName);
		} else if (this.defaults.getInitMethod() != null) { // eg1:defaults.getInitMethod()=null
			bd.setInitMethodName(this.defaults.getInitMethod());
			bd.setEnforceInitMethod(false);
		}

		/** 9:向bd中设置destroyMethodName和enforceDestroyMethod变量的值 */
		if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { // eg1:false,判断是否存在"destroy-method"属性
			String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
			bd.setDestroyMethodName(destroyMethodName);
		} else if (this.defaults.getDestroyMethod() != null) { // eg1:defaults.getDestroyMethod()=null
			bd.setDestroyMethodName(this.defaults.getDestroyMethod());
			bd.setEnforceDestroyMethod(false);
		}

		/** 10:向bd中设置factoryMethodName变量的值 */
		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) // eg1:false,判断是否存在"factory-method"属性
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));

		/** 11:向bd中设置factoryBeanName变量的值 */
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) // eg1:false,判断是否存在"factory-bean"属性
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));

		return bd;
	}

/** 4:向bd中设置autowireMode变量的值 */ 

	/** 解析给定的autowire属性值int autowire常量 */
	@SuppressWarnings("deprecation")
	public int getAutowireMode(String attrValue) {
		String attr = attrValue;
		if (isDefaultValue(attr)) // attr为空,或者 attr值为"default"
			attr = this.defaults.getAutowire(); // 从<beans>标签中的default-autowire属性获取默认值

		int autowire = AbstractBeanDefinition.AUTOWIRE_NO;
		if (AUTOWIRE_BY_NAME_VALUE.equals(attr)) 			// "byName"
			autowire = AbstractBeanDefinition.AUTOWIRE_BY_NAME;
		else if (AUTOWIRE_BY_TYPE_VALUE.equals(attr)) 		// "byType"
			autowire = AbstractBeanDefinition.AUTOWIRE_BY_TYPE;
		else if (AUTOWIRE_CONSTRUCTOR_VALUE.equals(attr)) 	// "constructor"
			autowire = AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR;
		else if (AUTOWIRE_AUTODETECT_VALUE.equals(attr)) 	// "autodetect"(Spring3.0之后不再支持,被废弃)
			autowire = AbstractBeanDefinition.AUTOWIRE_AUTODETECT;
		return autowire;
	}

/** 5:解析元数据 */

    <!-- meta 标签演示 -->
    <bean id="m416OfMeta" class="com.muse.springdemo.entity.Gun">
        <property name="name" value="M416"/>
        <property name="bulletNums" value="45"/>
        <meta key="desc" value="非常好用的一把枪"/>
    </bean>
    @Test
    void testMeta() {
        Gun gun = beanFactory.getBean("m416OfMeta", Gun.class);
        log.info("m416OfMeta={}", gun);
    }

 运行结果:

使用了meta标签后,配置的desc并不会体现在bean的属性当中,而只是一个额外的声明。 当需要使用里面的信息的时候,可以通过BeanDefinition的getAttribute(key)方法进行获取。对meta的解析:

			/** 5:解析元数据 */
			parseMetaElements(ele, bd);
	/** 解析给定元素下面的meta元素(如果有的话)*/
	public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
		NodeList nl = ele.getChildNodes(); // 获取当前节点的所有子节点列表
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			// node节点是候选人元素,并且node节点名称为"meta"
			if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) { // 只解析meta标签
				Element metaElement = (Element) node;
				String key = metaElement.getAttribute(KEY_ATTRIBUTE);  // meta标签中的key
				String value = metaElement.getAttribute(VALUE_ATTRIBUTE);   // meta标签中的value
				BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value); // 封装到BeanMetadataAttribute实例对象中
				attribute.setSource(extractSource(metaElement));
				attributeAccessor.addMetadataAttribute(attribute); // 将attribute保存到BeanDefinition中
			}
		}
	}
	/** 如果node是Element类型,并且 (node属于默认命名空间 或者 node的父节点不是默认命名空间),则返回true */
	private boolean isCandidateElement(Node node) {
		return (node instanceof Element && (isDefaultNamespace(node) || !isDefaultNamespace(node.getParentNode())));
	}

/** 6:解析lookup-method属性 */ 

lookup-method它的作用是获取器注入。即:获取器注入是一种特殊的方法注入,它是把 一个方法声明为返回某种类型的bean,但实际要返回的bean是在配置文件里面配置的, 此方法可用在设计有些可插拔的功能上,解除程序依赖。

			/** 6:解析lookup-method属性 */
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
	/**
	 * 解析给定bean元素的lookup-override子元素
	 */
	public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes(); // 获取当前节点的所有子节点列表
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) { // 只解析lookup-method标签
				Element ele = (Element) node;
				String methodName = ele.getAttribute(NAME_ATTRIBUTE);
				String beanRef = ele.getAttribute(BEAN_ELEMENT);
				LookupOverride override = new LookupOverride(methodName, beanRef); // 将lookup-method标签的配置信息封装为LookupOverride实例对象
				override.setSource(extractSource(ele));
				overrides.addOverride(override); // 将override保存到BeanDefinition中
			}
		}
	}

举例:

public interface Pen {
    void print();
}
public class Brush implements Pen {
    @Override
    public void print() {
        System.out.println("Brush print !");
    }
}
public class Pencil implements Pen {
    @Override
    public void print() {
        System.out.println("Pencil print !");
    }
}

public abstract class Writer {
    public void write() {
        getPen().print();
    }
    public abstract Pen getPen();
}
    <!-- lookup-method 标签 -->
    <bean id="writer" class="com.muse.springdemo.lookupmethod.Writer">
        <lookup-method name="getPen" bean="brush"/>
    </bean>
    <bean id="pencil" class="com.muse.springdemo.lookupmethod.Pencil"/>
    <bean id="brush" class="com.muse.springdemo.lookupmethod.Brush"/>
    @Test
    void testLookupMethod() {
        Writer writer = beanFactory.getBean("writer", Writer.class);
        writer.write();
    }

运行结果:

/** 7:解析replaced-method属性 */

replaced-mothod可以实现方法替换,通过实现MethodReplacer接口,可以在运行时用新的方法替换现有的方法。

举例:

public class Coder {
    public void shout() {
        System.out.println("老板!我要离职!我不想写代码了!烦死了!");
    }
}
public class CoderMethodReplacer implements MethodReplacer {
    @Override
    public Object reimplement(Object obj, Method method, Object[] args) {
        System.out.println("老板!我最爱写代码了!我会一直忠于公司为您工作的!");
        return null;
    }
}
    <!-- replaced-method 标签演示 -->
    <bean id="coder" class="com.muse.springdemo.replacedmethod.Coder"/>
    <bean id="fakerCoder" class="com.muse.springdemo.replacedmethod.Coder">
        <replaced-method name="shout" replacer="replacer"/>
    </bean>
    <bean id="replacer" class="com.muse.springdemo.replacedmethod.CoderMethodReplacer"/>
    @Test
    void testReplacedMethod() {
        Coder coder = beanFactory.getBean("coder", Coder.class);
        coder.shout();   // 输出结果:老板!我要离职!我不想写代码了!烦死了!
        Coder coder = beanFactory.getBean("fakerCoder", Coder.class);
        coder.shout();   // 输出结果:老板!我最爱写代码了!我会一直忠于公司为您工作的!
    }
			/** 7:解析replaced-method属性 */
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
	/**
	 * 解析给定bean元素的replaced-method子元素
	 */
	public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes(); // 获取当前节点<replaced-method .../>标签的所有子节点列表
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { // 只解析replaced-method标签
				Element replacedMethodEle = (Element) node;
				String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); // "name"
				String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); // "replacer"
				ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
				List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT); // "arg-type"
				for (Element argTypeEle : argTypeEles) {
					String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE); // "match"
					match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
					if (StringUtils.hasText(match)) {
						replaceOverride.addTypeIdentifier(match);
					}
				}
				replaceOverride.setSource(extractSource(replacedMethodEle)); // 将replaced-method标签的配置信息保存到replaceOverride实例对象中
				overrides.addOverride(replaceOverride); // 将replaceOverride保存到BeanDefinition中
			}
		}
	}

lookup-method和replaced-method都会写进overrides,调用overrides的时候,获取到的就是lookup-method和replaced-method。

/** 8:解析构造函数参数 */

parseConstructorArgElements(ele, bd);

关于构造函数的解析操作,其核心代码是在parsePropertyValue这个方法中的,其处理逻辑如下所示:

① 不处理description属性和meta属性。

② 获取<constructor-arg>标签下的ref属性和value属性。

③ 当发现——

        【情况1】同时存在ref属性和value属性;

        【情况2】存在ref/value属性 并且存在子元素;任意一种情况时,抛出异常。

④ 如果配置了ref属性,则将ref的属性值保存到RuntimeBeanReference实例对象中。 eg:<constructor-arg ref="xxxx">

⑤ 如果配置了value属性,则将value的属性值保存到TypedStringValue实例对象中。 eg:<constructor-arg value="xxxx">

⑥ 如果配置了子元素,则调用parsePropertySubElement方法进行子元素解析。

⑦ 如果上面3种情况都没配置,则直接抛出异常  

举例:

    <!-- constructor 标签演示 -->
    <bean id="cat" class="com.muse.springdemo.constructor.Cat">
        <constructor-arg index="0">
            <value>bob</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>5</value>
        </constructor-arg>
    </bean>
@AllArgsConstructor
@Data
public class Cat {
    private String name;
    private int age;
}
    @Test
    void testConstructor() {
        Cat cat = beanFactory.getBean("cat", Cat.class);
        log.info("cat={}", cat);
    }

运行结果:

	/**
	 * Parse constructor-arg sub-elements of the given bean element.
	 */
	public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
		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)) // 只解析constructor-arg标签
				parseConstructorArgElement((Element) node, bd);
		}
	}
	/**
	 * 解析constructor-arg元素
	 */
	public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE); 	// "index"
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE); 	// "type"
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); 	// "name"

		/** 1:如果配置了"index",则执行if内语句 */
		if (StringUtils.hasLength(indexAttr)) {
			try {
				int index = Integer.parseInt(indexAttr);
				if (index < 0) error("'index' cannot be lower than 0", ele);

				else {
					try {
						this.parseState.push(new ConstructorArgumentEntry(index));
						/** 1-1:解析属性值 */
						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));

						/** 1-2:判断index是否重复 */
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index))
							error("Ambiguous constructor-arg entries for index " + index, ele);
						else
							bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder); // 将index和对应的"具体值"保存到bd中
					}
					finally {
						this.parseState.pop();
					}
				}
			}
			catch (NumberFormatException ex) {
				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
			}
		}

		/** 2:如果没有为constructor配置"index"属性,则执行else这部分 */
		else {
			try {
				this.parseState.push(new ConstructorArgumentEntry());
				/** 2-1:解析属性值 */
				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); // 将值保存到BeanDefinition中
			}
			finally {
				this.parseState.pop();
			}
		}
	}

1-1:解析属性值

	/**
	 * 获取属性元素的值。可能是一个列表等等,也用于构造函数的参数
	 */
	@Nullable
	public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
		String elementName = (propertyName != null ?
				"<property> element for property '" + propertyName + "'" :
				"<constructor-arg> element");

		/** 1:获得<constructor-arg>标签下的子node列表 */
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			/** 1-2:不处理"description"元素和"meta"元素 */
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) {
				if (subElement != null)
					error(elementName + " must not contain more than one sub-element", ele);
				else
					subElement = (Element) node;
			}
		}

		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);		// 是否配置了"ref"属性
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); 	// 是否配置了"value"属性
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null))
			error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);

		/** 2:针对配置了"ref"属性进行解析操作 */
		if (hasRefAttribute) {
			String refName = ele.getAttribute(REF_ATTRIBUTE); // 获得"ref"属性值
			if (!StringUtils.hasText(refName))
				error(elementName + " contains empty 'ref' attribute", ele);
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(ele));
			return ref;
		}

		/** 3:针对配置了"value"属性进行解析操作 */
		else if (hasValueAttribute) {
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); // 获得"value"属性值
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}

		/** 4:针对存在子元素的情况进行解析操作 */
		else if (subElement != null) {
			return parsePropertySubElement(subElement, bd); // 解析子元素
		}

		/** 5:都不满足,抛出异常 */
		else {
			error(elementName + " must specify a ref or value", ele); // 都不满足,抛出异常
			return null;
		}
	}

/** 9:解析property子元素 */ 

parsePropertyElements(ele, bd);

解析property子元素,返回值使用PropertyValue进行封装,并记录在了BeanDefinition的 propertyValues属性里。 

	/**
	 * Parse property sub-elements of the given bean element.
	 */
	public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes(); // 获取当前节点的所有子节点列表
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) // 只解析property标签
				parsePropertyElement((Element) node, bd); // 解析property配置信息
		}
	}
	/**
	 * 解析属性元素
	 */
	public void parsePropertyElement(Element ele, BeanDefinition bd) {
		String propertyName = ele.getAttribute(NAME_ATTRIBUTE); // 获得"name"属性值
		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)) { // 如果发现name属性值重复,则报错
				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
				return;
			}
			Object val = parsePropertyValue(ele, bd, propertyName); // 解析property属性值
			PropertyValue pv = new PropertyValue(propertyName, val);
			parseMetaElements(ele, pv); // 解析meta属性值
			pv.setSource(extractSource(ele));
			bd.getPropertyValues().addPropertyValue(pv); // 将property属性值封装到PropertyValue实例对象中,然后保存到BeanDefinition
		}
		finally {
			this.parseState.pop();
		}
	}
	/**
	 * 获取属性元素的值。可能是一个列表等等,也用于构造函数的参数
	 */
	@Nullable
	public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
		String elementName = (propertyName != null ?
				"<property> element for property '" + propertyName + "'" :
				"<constructor-arg> element");

		/** 1:获得<constructor-arg>标签下的子node列表 */
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			/** 1-2:不处理"description"元素和"meta"元素 */
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) {
				if (subElement != null)
					error(elementName + " must not contain more than one sub-element", ele);
				else
					subElement = (Element) node;
			}
		}

		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);		// 是否配置了"ref"属性
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); 	// 是否配置了"value"属性
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null))
			error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);

		/** 2:针对配置了"ref"属性进行解析操作 */
		if (hasRefAttribute) {
			String refName = ele.getAttribute(REF_ATTRIBUTE); // 获得"ref"属性值
			if (!StringUtils.hasText(refName))
				error(elementName + " contains empty 'ref' attribute", ele);
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(ele));
			return ref;
		}

		/** 3:针对配置了"value"属性进行解析操作 */
		else if (hasValueAttribute) {
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); // 获得"value"属性值
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}

		/** 4:针对存在子元素的情况进行解析操作 */
		else if (subElement != null) {
			return parsePropertySubElement(subElement, bd); // 解析子元素
		}

		/** 5:都不满足,抛出异常 */
		else {
			error(elementName + " must specify a ref or value", ele); // 都不满足,抛出异常
			return null;
		}
	}

/** 10:解析qualifier子元素 */ 

parseQualifierElements(ele, bd);

进行匹配操作,没有指定bean名称的时候,比如使用类型去匹配的时候。

当同一类型的bean注入到 IOC 之后, Spring容器中匹配的候选Bean数目必须 有且仅有一个,那么此时,我们可以通过Qualifier指出注入Bean的名称,这样歧义就消除掉了。

由于@Autowired是根据类型进行匹配 的,所以可以搭配@Qualifier实现针对名称进行匹配

	/**
	 * Parse qualifier sub-elements of the given bean element.
	 */
	public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) // "qualifier"
				parseQualifierElement((Element) node, bd);
		}
	}
	/**
	 * 解析qualifier元素
	 */
	public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
		String typeName = ele.getAttribute(TYPE_ATTRIBUTE); // 获得"type"属性值
		if (!StringUtils.hasLength(typeName)) {
			error("Tag 'qualifier' must have a 'type' attribute", ele);
			return;
		}
		this.parseState.push(new QualifierEntry(typeName));
		try {
			AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
			qualifier.setSource(extractSource(ele));
			String value = ele.getAttribute(VALUE_ATTRIBUTE); // 获得"value"属性值
			if (StringUtils.hasLength(value))
				qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);

			// 获得qualifier下所有的子节点列表
			NodeList nl = ele.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) { // "attribute"
					Element attributeEle = (Element) node;
					String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE); // "key"
					String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE); // "value"
					if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
						BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
						attribute.setSource(extractSource(attributeEle));
						qualifier.addMetadataAttribute(attribute);
					}
					else {
						// 如果使用了attribute标签,则必须包含name和value属性值
						error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
						return;
					}
				}
			}
			bd.addQualifier(qualifier); // 将qualifier配置信息保存到AutowireCandidateQualifier实例对象中,并将其保存到BeanDefinition中
		}
		finally {
			this.parseState.pop();
		}
	}

回到 : /** 4: 解析配置文件中其它的属性,并封装为GenericBeanDefinition实例 */

		/** 4: 解析配置文件中其它的属性,并封装为GenericBeanDefinition实例 */
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) { // eg1:beanName="m416"
				try {
					if (containingBean != null)
						beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
				}
				catch (Exception ex) {
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases); // eg1:aliases.size()=0
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); // eg1:beanName="m416",aliasesArray=[]
		}

		return null;

以上代码的含义:如果beanName为空,就去解析beanName 

回到:

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // step1:元素解析
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            // step2:如果子节点下还有自定义标签,则对其进行解析
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
                // step3:对bdHoldr进行注册
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                BeanDefinitionStoreException ex = var5;
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
            }
            // step4:发送注册事件
            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

当Spring中标签的子元素使用了自定义标签配置,则会被该方法解析,如下所示:

 

step2:如果子节点下还有自定义标签,则对其进行解析

decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) 

    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
        return this.decorateBeanDefinitionIfRequired(ele, originalDef, (BeanDefinition)null);
    }
   // 如果适用的话,通过命名空间处理程序装饰给定的bean定义
    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
        BeanDefinitionHolder finalDefinition = originalDef;
        NamedNodeMap attributes = ele.getAttributes();
// 首先根据自定义属性进行装饰
// eg1: attribtes=[autowire="default",
// 				autowire-candidate="default",
// 				class="com.muse.springdemo.entiry.Gun",
// 				id="m416",
// 				lazy-init="default"]
        for(int i = 0; i < attributes.getLength(); ++i) {
            Node node = attributes.item(i);
            finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
        }
// 基于自定义嵌套元素进行装饰。
        NodeList children = ele.getChildNodes();

        for(int i = 0; i < children.getLength(); ++i) {
            Node node = children.item(i);
            if (node.getNodeType() == 1) {
                finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
            }
        }

        return finalDefinition;
    }

无论是对所有属性还是所有子节点的解析,都会执行decorateIfRequired方法, 其中,isDefaultNamespace(namespaceUri)是通过判断namespaceUri不为空,并且等于 "http://www.springframework.org/schema/beans",如果都满足,则是默认的命名空间。 否则是自定义的命名空间。 

    public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
        String namespaceUri = this.getNamespaceURI(node);  // 获得自定义标签的命名空间
// 只针对【自定义标签】进行解析
        if (namespaceUri != null && !this.isDefaultNamespace(namespaceUri)) {
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);  // 根据命名空间找到对应的处理器
            if (handler != null) {
                BeanDefinitionHolder decorated = handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));  // 执行修饰操作
                if (decorated != null) {
                    return decorated;
                }
            } else if (namespaceUri.startsWith("http://www.springframework.org/schema/")) {
                this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
            } else if (this.logger.isDebugEnabled()) {
                this.logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
            }
        }

        return originalDef;
    }

(以下先忽略) 

    @Nullable
    public NamespaceHandler resolve(String namespaceUri) {
        Map<String, Object> handlerMappings = this.getHandlerMappings();
        Object handlerOrClassName = handlerMappings.get(namespaceUri);
        if (handlerOrClassName == null) {
            return null;
        } else if (handlerOrClassName instanceof NamespaceHandler) {
            return (NamespaceHandler)handlerOrClassName;
        } else {
            String className = (String)handlerOrClassName;

            try {
                Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
                if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                    throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
                } else {
                    NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
                    namespaceHandler.init();
                    handlerMappings.put(namespaceUri, namespaceHandler);
                    return namespaceHandler;
                }
            } catch (ClassNotFoundException var7) {
                ClassNotFoundException ex = var7;
                throw new FatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex);
            } catch (LinkageError var8) {
                LinkageError err = var8;
                throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err);
            }
        }
    }

step4:发送注册事件(默认没有任何实现)

// 触发一个组件注册事件    
public void fireComponentRegistered(ComponentDefinition componentDefinition) {
        this.eventListener.componentRegistered(componentDefinition);
    }

step3:对bdHoldr进行注册

在下面的代码中,我们可以看到总共有两个步骤的操作,分别是:

① 注册beanName和BeanDefinition

② 注册beanName和alias别名

** 注册 beanName 和 BeanDefinition 

从方法registerBeanDefinition的代码中,我们可以看到针对bean的注册处理方式上,主 要进行了以下几个步骤:

① 对AbstractBeanDefinition的校验。在解析XML文件的时候我们提过校验,但是此 校验非彼校验,之前的校验是针对XML格式的校验,而此时的校验是针对于 AbstractBeanDefinition的methodOverrides属性和factoryMethodName的。

② 对beanName已经注册的情况的处理。如果设置了不允许bean的覆盖,则需要抛出 异常,否则直接覆盖。

③ 加入beanDefinitionMap缓存,更新beanName和BeanDefinition。

④ 清除解析之前留下的对应beanName的缓存

    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// 获得beanName,注册beanName和beanDefiniton
        String beanName = definitionHolder.getBeanName();   // eg1: beanName="m416"
// eg1: DefaultListableBeanFactory#registerBeanDefinition(…)
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 获得别名alias(如果有的话),注册bean的别名
        String[] aliases = definitionHolder.getAliases();   // eg1: aliases=[]
        if (aliases != null) {
            String[] var4 = aliases;
            int var5 = aliases.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String alias = var4[var6];
                registry.registerAlias(beanName, alias);    // SimpleAliasRegisstry#registerAlias
            }
        }

    }

注册beanName:

registerBeanDefinition(): 

	//---------------------------------------------------------------------
	// Implementation of BeanDefinitionRegistry interface
	//---------------------------------------------------------------------

	// eg1:beanName="m416"  beanDefinition=GenericBeanDefinition@2236
	@Override
	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");

		/** 1:针对于methodOverrides属性的校验 */
		if (beanDefinition instanceof AbstractBeanDefinition) { // eg1:true
			try {
				((AbstractBeanDefinition) beanDefinition).validate(); // 校验操作,不满足则抛出异常
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex);
			}
		}

		/** 2-1:对beanName已经注册情况的处理。如果设置了不允许bean的覆盖,则需要抛出异常,否则直接覆盖 */
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); // eg1:beanDefinitionMap.size()=0
		if (existingDefinition != null) { // eg1:existingDefinition=null
			if (!isAllowBeanDefinitionOverriding())
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			this.beanDefinitionMap.put(beanName, beanDefinition); // 更新beanName和BeanDefinition
		}

		/** 2-2:如果这个bean之前没有加载过,加入beanDefinitionMap缓存,更新beanName和BeanDefinition */
		else {
			// 如果bean已经开始被创建,则需要加锁处理
			if (hasBeanCreationStarted()) { // eg1:false
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition); // 更新beanName和BeanDefinition
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				this.beanDefinitionMap.put(beanName, beanDefinition); // 更新beanName和BeanDefinition
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		/** 3:清除解析之前留下的对应beanName的缓存 */
		if (existingDefinition != null || containsSingleton(beanName)) // eg1:false
			resetBeanDefinition(beanName);
		else if (isConfigurationFrozen()) // eg1:false
			clearByTypeCache();
	}

/** 1:针对于methodOverrides属性的校验 */

((AbstractBeanDefinition) beanDefinition).validate(); 的validate():

// 校验bean definition,不满足抛异常
public void validate() throws BeanDefinitionValidationException {
	// 存在(lookup-method或者replace-method属性)并且还存在factory-method属性,则不满足校验,直接抛出异常
	if (this.hasMethodOverrides() && this.getFactoryMethodName() != null) {
		throw new BeanDefinitionValidationException("Cannot combine factory method with container-generated method overrides: the factory method must create the concrete bean instance.");
	} else {
		if (this.hasBeanClass()) {    // eg1: 在bean创建成功的时候才有beanClass,当下还没有把配置加载完,所以返回false
			this.prepareMethodOverrides();
		}
	}
}
// 返回该定义是否指定bean类 
public boolean hasBeanClass() {
	// eg1: beanClass="com.muse.springdemo.entiry.Gun"
	return this.beanClass instanceof Class;    // eg1: false
}
// 验证并准备为该bean定义的方法覆盖,检查是否存在指定名称的方法
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    // 检查查找方法是否存在,并确定他们的重载状态
	if (this.hasMethodOverrides()) {
		this.getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
	}
}
// 验证并准备给定的方法覆盖,检查指定名称的方法是否存在,如果没有找到,则将其标记为重载
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
	// 获得指定类中某个方法名称被定义的方法个数
	int count = ClassUtils.getMethodCountForName(this.getBeanClass(), mo.getMethodName());
	if (count == 0) {
		throw new BeanDefinitionValidationException("Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + this.getBeanClassName() + "]");
	} else {
		if (count == 1) {
			mo.setOverloaded(false);   // 将重写标记为未重载
		}
	}
}

注册bean的别名:

举例:

    <!-- alias 标签演示 -->
    <bean id="ent" class="com.muse.springdemo.alias.Entitlement">
        <property name="name" value="Entitlement"/>
        <property name="time" value="50"/>
    </bean>
    <alias name="ent" alias="alias_ent"/>

SimpleAliasRegisstry#registerAlias

对alias标签的解析分为两部分:

第一部分:

注册别名Alias的方法registry.registerAlias(beanName, alias)处理逻辑:

① 若alias与beanName的值相同,则从aliasMap中移除原有alias。

② 否则,如果之前已经建立过name和alias的映射了,则直接返回即可。

③ alias循环检查,即:当A——>B存在时,若再出现B——>A,则会抛出异常。

④ 注册alias和beanName到aliasMap中。

	// eg1:name="ent", alias="alias_ent"
	@Override
	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) { // eg1:aliasMap.size()=0
			/** 1-1:如果name和alias名称相同,则移除别名alias映射 */
			if (alias.equals(name)) // eg1:false
				this.aliasMap.remove(alias);

			/** 1-2:如果之前已经建立过name和alias的映射了,则直接返回即可 */
			else {
				String registeredName = this.aliasMap.get(alias);
				if (registeredName != null) { // eg1:registeredName=null
					if (registeredName.equals(name))
						return;
					if (!allowAliasOverriding())
						throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
								name + "': It is already registered for name '" + registeredName + "'.");
				}
				/** 1-2-1:alias循环检查,当A——>B存在时,若再出现B——>A,则会抛出异常 */
				checkForAliasCircle(name, alias); // eg1:DefaultListableBeanFactory#checkForAliasCircle(name, alias)

				/** 1-2-2:维护alias与name之间的关系 */
				this.aliasMap.put(alias, name);
			}
		}
	}

以及:

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		/** 1:针对<import>标签进行解析 */
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT))
			importBeanDefinitionResource(ele);

		/** 2:针对<alias>标签进行解析 */
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT))
			processAliasRegistration(ele);

		/** 3:针对<bean>标签进行解析 */
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT))
			processBeanDefinition(ele, delegate);

		/** 4:针对<beans>标签进行解析 */
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT))
			doRegisterBeanDefinitions(ele);
	}

第一部分:

	/**
	 * 检查给定的名称是否已经作为另一个方向的别名指向了给定的别名,提前捕获循环引用并抛出相应的IllegalStateException。
	 */
	// eg1:name="ent", alias="alias_ent"
	protected void checkForAliasCircle(String name, String alias) {
		if (hasAlias(alias, name)) { // eg1:false
			throw new IllegalStateException("Cannot register alias '" + alias +
					"' for name '" + name + "': Circular reference - '" +
					name + "' is a direct or indirect alias for '" + alias + "' already");
		}
	}
	/**
	 * 确定给定的名称是否注册了给定的别名。
	 */
	// eg1:name="ent", alias="alias_ent"
	public boolean hasAlias(String name, String alias) {
		String registeredName = this.aliasMap.get(alias); // eg1: aliasMap.size()=0,registeredName=null
		return ObjectUtils.nullSafeEquals(registeredName, name) || // eg1:false
				(registeredName != null // eg1:false
				&& hasAlias(name, registeredName));
	}

第二部分:

在对bean进行定义时,除了使用id属性来指定名称之外,为了提供多个bean的名称,我 们可以使用alias标签来指定。例如,通过在标签中设置name属性来为bean设置 别名(alias)。如下所示:

<bean id="gun" name="m416, ak47" class="com.muse.Gun" />

另外,Spring还有另外一种声明别名的方式:

<bean id="gun" class="com.muse.Gun" />
<alias name="gun" alias="m416, ak47"/>
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	/** 2:针对<alias>标签进行解析 */
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT))
	processAliasRegistration(ele);
}
	/**
	 * 处理给定的alias元素,用注册表注册别名。
	 */
	protected void processAliasRegistration(Element ele) {
		/** 1:配置的name和alias必须都存在,否则输出异常 */
		String name = ele.getAttribute(NAME_ATTRIBUTE); 	// eg1:name="ent"
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE); 	// eg1:alias="alias_ent"
		boolean valid = true;
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele); // name不能为空
			valid = false;
		}
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele); // alias不能为空
			valid = false;
		}

		/** 2:执行name和alias的注册操作 */
		if (valid) {
			try {
				// eg1:name="ent", alias="alias_ent", SimpleAliasRegistry#registerAlias(name, alias)
				getReaderContext().getRegistry().registerAlias(name, alias);
			}
			catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, ex);
			}
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}

registerAlias(name, alias):跟上面的部分1相同。

import标签:

对于项目中的大量Spring配置文件而言,如果我们采取分模块维护,那么更易于我们的管 理。我们可以通过采用标签,来引入不同模块的配置文件,具体如下所示:

<beans>
    <import resource="order.xml" />
    <import resource="stock.xml" />
</beans>

import标签的解析逻辑: 

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	/** 1:针对<import>标签进行解析 */
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT))
		importBeanDefinitionResource(ele);
    }
}
	/**
	 * 解析“import”元素,并将给定资源中的bean定义加载到bean工厂中。 <import resource="order.xml"/>
	 */
	protected void importBeanDefinitionResource(Element ele) {
		/** 1:解析resource属性,如果没配置,则抛出异常 */
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE); // "resource"
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		/** 2:查看位置是绝对地址还是相对地址 */
		// Resolve system properties: e.g. "${user.dir}"
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
		Set<Resource> actualResources = new LinkedHashSet<>(4);
		boolean absoluteLocation = false;
		try {
			absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		}
		catch (URISyntaxException ex) {}

		/** 3-1:如果是绝对路径,则直接根据地址加载对应的配置文件 */
		if (absoluteLocation) {
			try {
				getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, ex);
			}
		}

		/** 3-2:如果是相对路径 */
		else {
			try {
				/** 3-2-1:优先使用Resource子类(VfsResource、FileSystemResource……)的方法尝试执行解析操作 */
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				if (relativeResource.exists()) {
					getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				/** 3-2-2:如果解析不成功,则将给定的相对路径应用于给定的Java资源路径进行解析 */
				else {
					String baseLocation = getReaderContext().getResource().getURL().toString();
					getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
			}
			catch (IOException ex) {
				getReaderContext().error("Failed to resolve current resource location", ele, ex);
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, ex);
			}
		}

		/** 4:解析后进行监听器激活处理 */
		Resource[] actResArray = actualResources.toArray(new Resource[0]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}
// eg1: text = "bean.xml"
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
// strictHelper = null 
	if (this.strictHelper == null) {
		this.strictHelper = this.createPlaceholderHelper(false);
	}
	return this.doResolvePlaceholders(text, this.strictHelper);
}
// eg1: text = "bean.xml"
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
	// placeholderPrefix = "${", placeholderSuffix = "}", valueSeparator = ":"
	return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix, this.valueSeparator, ignoreUnresolvablePlaceholders);
}
    private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
        return helper.replacePlaceholders(text, this::getPropertyAsRawString);
    }

beans标签:递归调用bean解析的过程。

location --> resource  --> document  --> beanDefinition   -->    -->

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值