前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring读源码系列02----默认标签解析过程

Spring读源码系列02----默认标签解析过程

作者头像
大忽悠爱学习
发布2022-05-10 16:20:51
7280
发布2022-05-10 16:20:51
举报
文章被收录于专栏:c++与qt学习

Spring读源码系列02----默认标签解析过程


本系列文章:

Spring读源码系列01—Spring核心类及关联性介绍


之前的流程建议大家看一下01篇

这里一句话简单概括一下01篇的流程: 定位xml文件资源,包装为Resource对象—>xml文件被解析为一颗DOM树,即Document对象—>BeanDefinitionDocumentReader负责对Document对象进行解析—>BeanDefinitionDocumentReader内部又把解析Document对象的事情委托给了BeanDefinitionParserDelegate来完成

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	    //对imprt标签进行处理
		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)) {

			doRegisterBeanDefinitions(ele);
		}
	}

Bean标签的解析及注册

在这里插入图片描述
在这里插入图片描述

DefaultBeanDefinitionDocumentReader#processBeanDefinition----对Bean标签进行处理的方法

代码语言:javascript
复制
	/**
	 * Process the given bean element, parsing the bean definition
	 * and registering it with the registry.
	 */
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	    //委托BeanDefinitionParserDelegate来对bean标签进行解析
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
		//对自定义子标签再进行处理---如果存在的话
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				//注册BeanDefinition
				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));
		}
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parseBeanDefinitionElement从xml配置信息—>BeanDefinition

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
	//这里的ele是bean标签
		return parseBeanDefinitionElement(ele, null);
	}

目标方法:

代码语言:javascript
复制
	/**
	 * Parses the supplied <bean> element. May return null
	 * if there were errors during parse. Errors are reported to the
	 */
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
	   //解析id属性
		String id = ele.getAttribute(ID_ATTRIBUTE);
		//解析name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
        
        //存放bean的别名的集合 
		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) {
		//分割name属性---得到的是别名数组
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			//加入别名集合
			aliases.addAll(Arrays.asList(nameArr));
		}
        
        //id规定了beanName   
		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
		    //beanName为空,就把别名数组中第一个元素拿出来作为beanName
			beanName = aliases.remove(0);
			if (logger.isTraceEnabled()) {
				logger.trace("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

		if (containingBean == null) {
		    //别名不能重复
			checkNameUniqueness(beanName, aliases, ele);
		}
         
        / 
		//传入bean标签,beanName,containingBean开始正式对bean标签进行解析得到beanDefinition
	   //返回的beanDefinition类型是GenericBeanDefinition
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		///
		
		if (beanDefinition != null) {
		//beanName为空---没给id,别名也没有该咋办?
			if (!StringUtils.hasText(beanName)) {
				try {
				//containingBean不为空
					if (containingBean != null)
					 {
					 //自动生成一个beanName
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
					//如果containingBean为空,那就通过下面的方式生成一个beanName
					//这里获得的beanName是全类名加上一个#0---->org.deepSpring.Bean#0
						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);
			//生成BeanDefinitionHolder----这个类干的事情就是整合了beanDefinition,beanName和aliasesArray
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parseBeanDefinitionElement—将bean标签映射到BeanDefinition

记住该类BeanDefinitionParserDelegate才是被委托解析xml生成BeanDefinition的对象

代码语言:javascript
复制
	/**
	 * Parse the bean definition itself, without regard to name or aliases. May return
	 null if problems occurred during the parsing of the bean definition.
	 */
	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
       //跟踪解析的状态
		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
		//获取bean标签里面的className属性
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
		//获取bean标签里面的parent属性
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
		    //生成BeanDefinition
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
           
           //硬编码解析默认bean的各种属性---因为BeanDefinition里面成员属性和bean标签里面能写的属性一一映射
           //这样的话,每解析出一个属性,就直接设置BeanDefinition对应映射到的值即可
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			//提取description
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
            
            //解析元数据 
			parseMetaElements(ele, bd);
			//解析lookup-method属性
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			//解析replace-method属性
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

           //解析构造函数参数
			parseConstructorArgElements(ele, bd);
			//解析property子元素
			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;
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#createBeanDefinition创建用于属性承载的BeanDefinition
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
			throws ClassNotFoundException {
           //BeanDefinitionReaderUtils来创建BeanDefinition
           //这个工具类还可以用来生成beanName,注册BeanDefinition上面都讲到过了
		return BeanDefinitionReaderUtils.createBeanDefinition(
				parentName, className, this.readerContext.getBeanClassLoader());
	}
代码语言:javascript
复制
BeanDefinitionReaderUtils类:

	public static AbstractBeanDefinition createBeanDefinition(
			@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
        //创建的是GenericBeanDefinition
		GenericBeanDefinition bd = new GenericBeanDefinition();
		bd.setParentName(parentName);
		if (className != null) {
			if (classLoader != null) {
				bd.setBeanClass(ClassUtils.forName(className, classLoader));
			}
			else {
				bd.setBeanClassName(className);
			}
		}
		return bd;
	}

BeanDefinitionParserDelegate#parseBeanDefinitionAttributes—解析bean标签上能标注的各种属性
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下面我们开始对bean标签里面的属性进行解析了

代码语言:javascript
复制
	/**
	 * Apply the attributes of the given bean element to the given bean * definition.
	 * @param ele bean declaration element
	 * @param beanName bean name
	 * @param containingBean containing bean definition
	 * @return a bean definition initialized according to the bean element attributes
	 */
	public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
        //解析scope属性  
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}
		else if (containingBean != null) {
		     //如果是内嵌的beanDefinition情况下,没有单独指定scope属性,则使用父类的默认属性    
			// 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属性 
		String lazyInit =  ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		if (isDefaultValue(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		//如果没有数组,或设置成其他字符都会被设置成false---即默认都不是懒惰初始化的
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
        
        //解析autowire属性  
		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		//设置自动注入模式--构造器注入,按照类型注入等
		bd.setAutowireMode(getAutowireMode(autowire));
          
          //解析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 (isDefaultValue(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);
			bd.setInitMethodName(initMethodName);
		}
		else if (this.defaults.getInitMethod() != null) {
			bd.setInitMethodName(this.defaults.getInitMethod());
			bd.setEnforceInitMethod(false);
		}
        
        //解析destory-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;
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parseMetaElements—解析元数据

解析完bean标签上面可以标注的所有属性后,下面开始解析bean标签内部可以使用过的子标签,从< meta >标签开始

代码语言:javascript
复制
    <bean name="dhy,xpy" id="myTestBean" class="org.deepSpring.Bean">
        <meta key="dhy" value="xpy"/>
    </bean>
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
//这里的ele是bean标签,BeanMetadataAttributeAccessor 是AbstractBeanDefinition,上面讲过AbstractBeanDefinition继承了该类
//该类是用来统一管理元数据信息的类
	public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
	// 获取当前节点的所以子元素
		NodeList nl = ele.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			//提取meta
			if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
				Element metaElement = (Element) node;
				String key = metaElement.getAttribute(KEY_ATTRIBUTE);
				String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
				//BeanMetadataAttribute对元数据的key,value进行封装
				BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
				attribute.setSource(extractSource(metaElement));
				//加入MetadataAttribute集合中
				attributeAccessor.addMetadataAttribute(attribute);
			}
		}
	}

BeanDefinitionParserDelegate#parseLookupOverrideSubElements—解析子元素lookup-method
在这里插入图片描述
在这里插入图片描述

我打赌很多人可能都不知道这个属性干啥用的,下面我简单通过一个例子介绍一下:

代码语言:javascript
复制
public abstract class Test {
  public void Show()
  {
      getPeo().Show();
  }
  public abstract Peo getPeo();
}
代码语言:javascript
复制
public class Peo {
    public void Show()
    {
        System.out.println("我是人");
    }
}

如果我们想让Test对象被代理,然后其getPeo方法由代理对象实现,返回一个Peo类型的bean,可以通过lookup-method属性完成,当前注解直接标注在getPeo方法上也可以,这里不进行演示了:

代码语言:javascript
复制
    <bean id="Test" class="org.deepSpring.Test">
        <lookup-method name="getPeo" bean="Peo"></lookup-method>
    </bean>
    <bean id="Peo" class="org.deepSpring.Peo"></bean>

测试:

代码语言:javascript
复制
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml"));
        Test bean = beanFactory.getBean(Test.class);
        bean.Show();
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

下面让我们走进parseLookupOverrideSubElements的方法

代码语言:javascript
复制
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
代码语言:javascript
复制
	/**
	 * Parse lookup-override sub-elements of the given bean element.
	 * beanEle是bean标签,MethodOverrides 是BeanDefintion里面存放这种需要被重写的方法集合
	 */
	public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			//当前bean的子元素为LOOKUP_METHOD---其实大家可以发现,对一个属性进行解析的流程是类似的
			if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
				Element ele = (Element) node;
				//获取要修饰的方法
				String methodName = ele.getAttribute(NAME_ATTRIBUTE);
				//获取要配置返回的bean
				String beanRef = ele.getAttribute(BEAN_ELEMENT);
				//LookupOverride对上面两个属性进行封装---这个步骤和对元数据的封装思想一致
				LookupOverride override = new LookupOverride(methodName, beanRef);
				override.setSource(extractSource(ele));
				//加入需要被覆盖的方法集合
				overrides.addOverride(override);
			}
		}
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parseReplacedMethodSubElements—解析子元素replace-method
在这里插入图片描述
在这里插入图片描述

还是举个小例子吧:

代码语言:javascript
复制
public class Peo {
    public void Show()
    {
        System.out.println("我是人");
    }
}

如果我们要在运行期间替换掉Peo的show方法,或者对其进行方法增强该怎么办呢? —AOP,不不不,后面再聊,我们现在可以用MethodReplacer 办到:

代码语言:javascript
复制
public class MyReplacer implements MethodReplacer {
    @Override
    public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
        System.out.println("replace method");
        return null;
    }
}

配置文件:

代码语言:javascript
复制
    <bean id="Peo" class="org.deepSpring.Peo">
        <replaced-method name="Show" replacer="MyReplacer"></replaced-method>
    </bean>
    <bean id="MyReplacer" class="org.deepSpring.MyReplacer"></bean>

测试类:

代码语言:javascript
复制
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml"));
        Peo bean = beanFactory.getBean(Peo.class);
        bean.Show();
在这里插入图片描述
在这里插入图片描述

非常类似动态代理,懂得都懂,不懂我也就不多说了


回到replace-method方法进行解析的地方:

代码语言:javascript
复制
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

对应方法源码:

代码语言:javascript
复制
	/**
	 * Parse replaced-method sub-elements of the given bean element.
	 */
	public void parseReplacedMethodSubElements(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, REPLACED_METHOD_ELEMENT)) {
			    //拿到<replaced-method>该标签
				Element replacedMethodEle = (Element) node;
				//方法名
				String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
				//replacer
				String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
				//ReplaceOverride进行封装
				ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
				// Look for arg-type match elements.
				List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
				for (Element argTypeEle : argTypeEles) {
				//记录参数
					String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
					match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
					if (StringUtils.hasText(match)) {
						replaceOverride.addTypeIdentifier(match);
					}
				}
				replaceOverride.setSource(extractSource(replacedMethodEle));
				//这里还是添加进overrides集合
				overrides.addOverride(replaceOverride);
			}
		}
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parseConstructorArgElements----解析子元素constructor-arg
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
    <bean id="peo" class="org.deepSpring.Peo">
          <!--默认情况下是按照参数的顺序注入,当指定index索引后就可以改变注入参数的顺序        -->
        <constructor-arg index="0">
            <value>大忽悠</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>18</value>
        </constructor-arg>
    </bean>
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
		parseConstructorArgElements(ele, bd);

方法对应源码:

代码语言:javascript
复制
	/**
	 * 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);
			//只解析<constructor-arg>标签
			if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
			//这里之所以将解析逻辑放到其他方法中进行实现,是因为构造函数逻辑处理比较复杂
				parseConstructorArgElement((Element) node, bd);
			}
		}
	}
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	/**
	 * Parse a constructor-arg element.
	 * 这里传入的Element 标签是constructor-arg 
	 */
	public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
	//提取Index,type,name属性
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		//如果设置了index属性---即规定了当前构造参数对应的索引----按照index指定位置进行注入
		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));
				        //constructor-arg标签对应的值进行解析
						Object value = parsePropertyValue(ele, bd, null);
						//通过一个ValueHolder来构造函数参数对应的值
						ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
					   //尝试去设置type和name属性
						if (StringUtils.hasLength(typeAttr)) {
							valueHolder.setType(typeAttr);
						}
						if (StringUtils.hasLength(nameAttr)) {
							valueHolder.setName(nameAttr);
						}
						valueHolder.setSource(extractSource(ele));
						//条件成立,说明存在两个以上的constructor-arg标签的index有重复,显然这不合理
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
						//否则添加进集合----参数索引和该位置索引处构造参数的值,该映射关系保存在indexedArgumentValues集合中
						//indexedArgumentValues是一个map集合
							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 {
		//没有设置index属性---按照参数的顺序注入
			try {
			//追踪解析状态--这里大家不要纠结,前期不是重点
				this.parseState.push(new ConstructorArgumentEntry());
				//constructor-arg标签对应的值进行解析
				Object value = parsePropertyValue(ele, bd, null);
				//ValueHolder封装当前索引处对应的参数值
				ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
				//尝试去设置type和name
				if (StringUtils.hasLength(typeAttr)) {
					valueHolder.setType(typeAttr);
				}
				if (StringUtils.hasLength(nameAttr)) {
					valueHolder.setName(nameAttr);
				}
				valueHolder.setSource(extractSource(ele));
				//这里就默认按照参数的顺序注入----这里参数保存的位置是在genericArgumentValues
				//genericArgumentValues是一个list集合
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
			}
			finally {
				this.parseState.pop();
			}
		}
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parsePropertyValue—解析constructor-arg标签中的值
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
        <constructor-arg index="0">
        //该方法解析此处的标签内容,显然这里只能写value,list,或者ref标签
        //解析后,返回该标签内部的值
            <value>大忽悠</value>
        </constructor-arg>

还可以这样写
	    <constructor-arg index="1" value="张三"></constructor-arg>
		<constructor-arg index="0" ref="bean1"></constructor-arg>
代码语言:javascript
复制
	/**
	 * Get the value of a property element. May be a list etc.
	 * Also used for constructor arguments, "propertyName" being null in this case.
	 * 因为<constructor-arg>没有<constructor-arg name="xxx">的用法,
	 * 但是<property name="name">是有的,因此要注意
	 */
	@Nullable
	public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
		String elementName = (propertyName != null ?
				"<property> element for property '" + propertyName + "'" :
				"<constructor-arg> element");
         //一种属性只能对应一种类型ref, value, list.
		// Should only have one child element: ref, value, list, etc.
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			//对DESCRIPTION_ELEMENT和META_ELEMENT不进行解析
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
					!nodeNameEquals(node, META_ELEMENT)) {
					//这里为啥要判断,很简单,因为一个<constructor-arg>标签下最多只能有一个value标签吧,你搞两个出来,这不合适吧
				// Child element is what we're looking for.
				if (subElement != null) {
					error(elementName + " must not contain more than one sub-element", ele);
				}
				else {
				//拿到<constructor-arg>下面的子标签
					subElement = (Element) node;
				}
			}
		}
        //尝试去获取该ele这里是construct-arg标签的ref属性和value属性
        //注意这里不是subElement 子标签                
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
		//子标签上不能同时有ref和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);
		}
        
        //如果construct-arg标签上有ref属性
		if (hasRefAttribute) {
		//拿到ref指向的refName
			String refName = ele.getAttribute(REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			//RuntimeBeanReference封装引用类型
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(ele));
			//直接返回
			return ref;
		}
		//如果construct-arg标签上有value属性
		else if (hasValueAttribute) {
		//用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;
		}
	}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parsePropertySubElement—解析constructor-arg标签下的子标签
代码语言:javascript
复制
	/**
	 * Parse a value, ref or collection sub-element of a property or
	 * constructor-arg element.
	 * @param ele subelement of property element; we don't know which yet
	 * @param bd the current bean definition (if any)
	 */
	@Nullable //这里的ele就是对应需要解析的子标签了
	public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
		return parsePropertySubElement(ele, bd, null);
	}
代码语言:javascript
复制
	/**
	 * Parse a value, ref or collection sub-element of a property or
	 * constructor-arg element.
	 * @param ele subelement of property element; we don't know which yet
	 * @param bd the current bean definition (if any)
	 * @param defaultValueType the default type (class name) for any
	 * {@code <value>} tag that might be created
	 */
	@Nullable
	public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {        
	//因为子标签可能是用户自定义的,因此需要判断一下
		if (!isDefaultNamespace(ele)) {
		//调用用户自定义实现的接口进行解析
			return parseNestedCustomElement(ele, bd);
		}
		//子标签是bean类型标签
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
		//如何解析bean标签----parseBeanDefinitionElement大家可以翻到上面梦开始的地方,我们现在还在梦中,快要醒了
			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
			if (nestedBd != null) {
				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
			}
			//解析出来BeanDefinitionHolder ,然后返回
			return nestedBd;
		}
		//子标签是ref类型的
		else if (nodeNameEquals(ele, REF_ELEMENT)) {
			// A generic reference to any name of any bean.
			String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
			boolean toParent = false;
			//如果refName没找到
			if (!StringUtils.hasLength(refName)) {
				// A reference to the id of another bean in a parent context.
				//可能是继承了parent标签的内容,去找parent属性
				refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
				toParent = true;
				if (!StringUtils.hasLength(refName)) {
					error("'bean' or 'parent' is required for <ref> element", ele);
					return null;
				}
			}
			if (!StringUtils.hasText(refName)) {
				error("<ref> 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;
		}
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parsePropertyElements----解析子元素property
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
parsePropertyElements(ele, bd);

方法源码:

代码语言:javascript
复制
	/**
	 * 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方法进行解析
				parsePropertyElement((Element) node, bd);
			}
		}
	}
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	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 {
		//name属性不能重复呀!!!
			if (bd.getPropertyValues().contains(propertyName)) {
				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
				return;
			}
			//传入prorperty标签和对应标注的name,得到property里面的值---
			//这个函数就是上面构造参数解析得到<construct-agr>标签里面值的时候用到的函数,不清楚的回看上面的讲解
			//propertyName只是用来做错误日志记录的,没别的用,因此解析过程和构造参数一模一样
			Object val = parsePropertyValue(ele, bd, propertyName);
			//PropertyValue进行封装---其实大概思路都这样,针对不同的标签,用一个类对得到的结果进行封装
			PropertyValue pv = new PropertyValue(propertyName, val);
			//解析元数据标签
			parseMetaElements(ele, pv);
			pv.setSource(extractSource(ele));
			//加入BeanDefinition的PropertyValue集合
			bd.getPropertyValues().addPropertyValue(pv);
		}
		finally {
			this.parseState.pop();
		}
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionParserDelegate#parseQualifierElements----解析子元素qualifier
代码语言:javascript
复制
	/**
	 * 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)) {
				parseQualifierElement((Element) node, bd);
			}
		}
	}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
/**
	 * Parse a qualifier element.
	 */
	public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
	//获取到type值
		String typeName = ele.getAttribute(TYPE_ATTRIBUTE);
		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));
			//获取value
			String value = ele.getAttribute(VALUE_ATTRIBUTE);
			if (StringUtils.hasLength(value)) {
				qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
			}
			//下面可能还有子标签
			NodeList nl = ele.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				//qualifer标签下面是否有attribute标签
				if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
					Element attributeEle = (Element) node;
					String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
					String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
					if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
						BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
						attribute.setSource(extractSource(attributeEle));
						qualifier.addMetadataAttribute(attribute);
					}
					else {
						error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
						return;
					}
				}
			}
			//添加到beanDefinition的qualifiers集合中
			bd.addQualifier(qualifier);
		}
		finally {
			this.parseState.pop();
		}
	}

AbstractBeanDefinition属性

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {

	/**
	 * 默认bean的作用域范围
	 */
	public static final String SCOPE_DEFAULT = "";

	/**
	 * 自动注入模式---不进行注入
	 */
	public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

	/**
	 * 按照名字进行注入
	 */
	public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

	/**
	 * 按照类型进行注入
	 */
	public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

	/**
	 * 通过构造函数参数进行注入
	 */
	public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

	/**
	 * 自动判断如何进行注入
	 */
	@Deprecated
	public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

	/**
	 * Constant that indicates no dependency check at all.
	 */
	public static final int DEPENDENCY_CHECK_NONE = 0;

	/**
	 * Constant that indicates dependency checking for object references.
	 */
	public static final int DEPENDENCY_CHECK_OBJECTS = 1;

	/**
	 * Constant that indicates dependency checking for "simple" properties.
	 */
	public static final int DEPENDENCY_CHECK_SIMPLE = 2;

	/**
	 * Constant that indicates dependency checking for all properties
	 */
	public static final int DEPENDENCY_CHECK_ALL = 3;

	/**
	 * Constant that indicates the container should attempt to infer the
	 * {@link #setDestroyMethodName destroy method name} for a bean as opposed to
	 * explicit specification of a method name. The value {@value} is specifically
	 * designed to include characters otherwise illegal in a method name, ensuring
	 * no possibility of collisions with legitimately named methods having the same
	 * name.
	 * <p>Currently, the method names detected during destroy method inference
	 * are "close" and "shutdown", if present on the specific bean class.
	 */
	public static final String INFER_METHOD = "(inferred)";


	@Nullable //目标对象className
	private volatile Object beanClass;

	@Nullable//默认作用域范围
	private String scope = SCOPE_DEFAULT;
    
    //bean标签可以标注abstract属性--是否抽象
	private boolean abstractFlag = false;

	@Nullable//是否懒加载
	private Boolean lazyInit;
   
   //当前Bean的自动注入模式
	private int autowireMode = AUTOWIRE_NO;

//依赖检查
	private int dependencyCheck = DEPENDENCY_CHECK_NONE;

//一个bean实例化前,需要依赖其他的bean的集合
	@Nullable
	private String[] dependsOn;

  //容器在查找自动装配对象的时候,是否会将该bean作为bean自动装配的候选者
	private boolean autowireCandidate = true;

//当存在多个bean的候选者时,将作为首选者
	private boolean primary = false;

//用于记录Qualifier
	private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();

	 //Specify a callback for creating an instance of the bean,
	 //as an alternative to a declaratively specified factory method.
	 //If such a callback is set, it will override any other constructor
	 // or factory method metadata. However, bean property population and
	 // potential annotation-driven injection will still apply as usual.
	@Nullable
	private Supplier<?> instanceSupplier;

//是否能够访问非公开的构造器和方法
	private boolean nonPublicAccessAllowed = true;

//是否以一种宽松的模式解析构造函数
//如果为false,那么下面的场景会抛出异常
//interface Test1{}
//class Test2 implements Test1{};
//class Main{
//Main(Test1){}; Main(Test2){}; 
//}
	private boolean lenientConstructorResolution = true;

//bean属性的factory-bean
	@Nullable
	private String factoryBeanName;
//bean属性的factory-method
	@Nullable
	private String factoryMethodName;

//记录构造函数的属性
	@Nullable
	private ConstructorArgumentValues constructorArgumentValues;
//普通属性集合
	@Nullable
	private MutablePropertyValues propertyValues;
//方法重写的持有者----lookup-method和replace-method
	private MethodOverrides methodOverrides = new MethodOverrides();
//初始化方法---init-method
	@Nullable
	private String initMethodName;
//destory-method
	@Nullable
	private String destroyMethodName;
//是否执行Init-method
	private boolean enforceInitMethod = true;
//是否执行destory-method
	private boolean enforceDestroyMethod = true;
//是否是用户定义的而不是应用程序本身定义的,创建aop的时候为true
	private boolean synthetic = false;
//定义这个bean的应用,APPLICATION:用户,INFRASTRUCTER:完全内部使用,与用户无关
//SUPPORT:某些复杂配置的一部分
	private int role = BeanDefinition.ROLE_APPLICATION;
//bean的描述信息
	@Nullable
	private String description;
//这个bean定义的资源
	@Nullable
	private Resource resource;
	....
}

解析默认标签中的自定义标签

在这里插入图片描述
在这里插入图片描述

应该是从BeanDefinitionDocumentReader类的parseBeanDefinitions方法处开始,我们第一次看到了对自定义和默认标签的区分解析,但是这里我要说的不是在此处,因为这里是对根标签层面进行区分的,例如:beans标签

代码语言:javascript
复制
	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);
		}
	}

我们着眼点先放在beans下一级标签中的自定义标签,那就只能从对bean标签底下的自定义标签找起来了

代码语言:javascript
复制
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		//重新来到梦的起点
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

让我们再来回归梦的起点

代码语言:javascript
复制
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	//大家不要糊涂了,我们上面一直都是对parseBeanDefinitionElement这一个函数进行分析的
	//该函数解析完根标签bean后,会返回一个对应的BeanDefinitionHolder 
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
		//然后就是下面这行代码-----我们开始分析是否需要对自定义标签进行解析
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				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));
		}
	}

BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired---->对默认bean标签下的自定义配置进行解析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	/**
	 * Decorate the given bean definition through a namespace handler, if applicable.
	 * @param ele the current element
	 * @param originalDef the current bean definition
	 * @return the decorated bean definition
	 */
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
		return decorateBeanDefinitionIfRequired(ele, originalDef, null);
	}
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	/**
	 * Decorate the given bean definition through a namespace handler, if applicable.
	 * @param ele the current element
	 * @param originalDef the current bean definition
	 * @param containingBd the containing bean definition (if any)
	 * @return the decorated bean definition
	 */
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
        //上一步解析完自定义标签后返回的BeanDefinitionHolder 
		BeanDefinitionHolder finalDefinition = originalDef;

		// Decorate based on custom attributes first.
		//遍历所有属性,查看是否有适用于修饰的属性
		NamedNodeMap attributes = ele.getAttributes();
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// Decorate based on custom nested elements.
		NodeList children = ele.getChildNodes();
		//遍历所有子节点,查看是否有适用于修饰的子元素
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}

BeanDefinitionParserDelegate#decorateIfRequired---->根据自定义命名空间寻找对应的命名空间处理器
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	/**
	 * Decorate the given bean definition through a namespace handler,
	 * if applicable.
	 * @param node the current child node
	 * @param originalDef the current bean definition
	 * @param containingBd the containing bean definition (if any)
	 * @return the decorated bean definition
	 */
	public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
          //获取自定义标签的命名空间
		String namespaceUri = getNamespaceURI(node);
		//命名空间不为空,并且不是默认命名空间
		if (namespaceUri != null && !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/")) {
				error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
			}
			else {
				// A custom namespace, not to be handled by Spring - maybe "xml:...".
				if (logger.isDebugEnabled()) {
					logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
				}
			}
		}
		return originalDef;
	}
在这里插入图片描述
在这里插入图片描述

注册解析的BeanDefinition

在这里插入图片描述
在这里插入图片描述

DefaultBeanDefinitionDocumentReader#processBeanDefinition

BeanDefinitionReaderUtils.registerBeanDefinition---->注册解析的BeanDefinition

代码语言:javascript
复制
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				//下面分析这一行代码:
				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));
		}
	}

代码语言:javascript
复制
	/**
	 * Register the given bean definition with the given bean factory.
	 * @param definitionHolder the bean definition including name and aliases
	 * @param registry the bean factory to register with
	 * @throws BeanDefinitionStoreException if registration failed
	 */
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		//注册bean的定义
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
			//注册bean的别名
				registry.registerAlias(beanName, alias);
			}
		}
	}
在这里插入图片描述
在这里插入图片描述

BeanDefinitionRegistry#registerBeanDefinition---->通过beanName注册BeanDefinition

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	//---------------------------------------------------------------------
	// Implementation of BeanDefinitionRegistry interface
	//---------------------------------------------------------------------

	@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");
         //类型判断---AbstractBeanDefinition中实现了大部分的功能
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
			//这里的校验主要是对于AbstractBeanDefinition属性中的methodOverrides校验,
			//校验methodOverrides是否与工厂方法并存或者methodOverrides对于的方法根本不存在
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
       
       //尝试从当前beanDefinitionMap中取出当前beanNam对应的beanDefinition
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		//是否需要覆盖
		if (existingDefinition != null) {
		//说明当前beanName对应的BeanDefinition 在容器中已经存在了
		//是否允许覆盖BeanDefinition 
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			//根据角色基本进行判断---主要是进行日志输出,如果发生了高级角色覆盖低级角色放入的BeanDefinition 
			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 + "]");
				}
			}
			//这两个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 + "]");
				}
			}
			//这两个BeanDefinition 相同
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			//如果允许覆盖就放入beanDefinitionMap覆盖原有的BeanDefinition 
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
	//检查这个工厂的 bean 创建阶段是否已经开始,即在此期间是否有任何 bean 被标记为已创建。
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				//beanDefinitionMap是全局变量,当有多个组合的原子性操作的时候,会存在并发访问的问题
				synchronized (this.beanDefinitionMap) {
				//放入beanDefinitionMap中
					this.beanDefinitionMap.put(beanName, beanDefinition);
				//更新已经记录的beanName---beanDefinitionNames
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					//从集合中移除这个已经注册过的单例名称---manualSingletonNames
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}
        
        //containsSingleton(beanName) ===> this.singletonObjects.containsKey(beanName)
		if (existingDefinition != null || containsSingleton(beanName)) {
		//重置所有beanName对应的缓存
			resetBeanDefinition(beanName);
		}
		else if (isConfigurationFrozen()) {
			clearByTypeCache();
		}
	}
在这里插入图片描述
在这里插入图片描述

SimpleAliasRegistry#registerAlias---->通过别名注册BeanDefinition

代码语言:javascript
复制
    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) {
        //如果beanName与alias相同的话不记录alias,并删除对应的alias
            if (alias.equals(name)) {
                this.aliasMap.remove(alias);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
                }
            } else {
            //判断该别名是否注册过
                String registeredName = (String)this.aliasMap.get(alias);
                if (registeredName != null) {
                //注册过,并且该别名对应的值就是当前beanName,那就不需要再管了
                    if (registeredName.equals(name)) {
                        return;
                    }
                  
                  //如果当前别名对应的beanName与当前需要注册的beanName不一致,那么判断别名的指向是否可以被覆盖
                    if (!this.allowAliasOverriding()) {
                        throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'.");
                    }

                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Overriding alias '" + alias + "' definition for registered name '" + registeredName + "' with new target name '" + name + "'");
                    }
                }
                  //当A->B存在时,如果再次出现A->C->B时候则会存在异常
                this.checkForAliasCircle(name, alias);
                //进行注册操作
                this.aliasMap.put(alias, name);
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
                }
            }

        }
    }
在这里插入图片描述
在这里插入图片描述

通知监听器解析及注册完成

代码语言:javascript
复制
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			//给注册的监听器发送事件,告知beanDefinition创建完毕
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
在这里插入图片描述
在这里插入图片描述

补充说明—>ReaderContext

这一点是书上没有的,但是因为源码中反复出现,我还是拿出来讲一下吧,毕竟有些东西并不难,但是你不知道的话,就会很懵逼

ReaderContext中的Reader指的是BeanDefinitionReader,即BeanDefinitionReader的上下文环境

代码语言:javascript
复制
public class XmlBeanFactory extends DefaultListableBeanFactory {
//XmlBeanFactory内部有一个XmlBeanDefinitionReader 的实例对象
	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
...
	}

我们来看一下XmlBeanDefinitionReader :

代码语言:javascript
复制
//XmlBeanDefinitionReader 内部有这样一个属性
	private ReaderEventListener eventListener = new EmptyReaderEventListener();
代码语言:javascript
复制
//XmlBeanDefinitionReader类中提供了一个设置eventListener 的方法,如果传入null值,则默认为EmptyReaderEventListener
	public void setEventListener(@Nullable ReaderEventListener eventListener) {
		this.eventListener = (eventListener != null ? eventListener : new EmptyReaderEventListener());
	}
代码语言:javascript
复制
//该方法也用到了eventListener---只不过这回是为了创建XmlReaderContext作为参数传入的
	public XmlReaderContext createReaderContext(Resource resource) {
		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
				this.sourceExtractor, this, getNamespaceHandlerResolver());
	}

createReaderContext在下面这个熟悉的方法中被调用,该方法是在将xml解析为Document对象后,创建BeanDefinitionDocumentReader后,调用其registerBeanDefinitions方法时,调用了createReaderContext方法

代码语言:javascript
复制
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

并且在BeanDefinitionDocumentReader内部会通过一个成员变量将作为参数传入的readerContext保存下来,然后后面很多地方都会用到这个上下文环境

代码语言:javascript
复制
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	//保存该环境对象
		this.readerContext = readerContext;
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

下面就来看看这个上下文环境对象都有啥功能吧:

代码语言:javascript
复制
public class XmlReaderContext extends ReaderContext {

	private final XmlBeanDefinitionReader reader;

	private final NamespaceHandlerResolver namespaceHandlerResolver;


	/**
	 * Construct a new {@code XmlReaderContext}.
	 * @param resource the XML bean definition resource
	 * @param problemReporter the problem reporter in use
	 * @param eventListener the event listener in use
	 * @param sourceExtractor the source extractor in use
	 * @param reader the XML bean definition reader in use
	 * @param namespaceHandlerResolver the XML namespace resolver
	 */
	public XmlReaderContext(
			Resource resource, ProblemReporter problemReporter,
			ReaderEventListener eventListener, SourceExtractor sourceExtractor,
			XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {

		super(resource, problemReporter, eventListener, sourceExtractor);
		this.reader = reader;
		this.namespaceHandlerResolver = namespaceHandlerResolver;
	}


	/**
	 * Return the XML bean definition reader in use.
	 */
	public final XmlBeanDefinitionReader getReader() {
		return this.reader;
	}

	/**
	 * Return the bean definition registry to use.
	 * @see XmlBeanDefinitionReader#XmlBeanDefinitionReader(BeanDefinitionRegistry)
	 */
	public final BeanDefinitionRegistry getRegistry() {
		return this.reader.getRegistry();
	}

	/**
	 * Return the resource loader to use, if any.
	 * <p>This will be non-null in regular scenarios,
	 * also allowing access to the resource class loader.
	 * @see XmlBeanDefinitionReader#setResourceLoader
	 * @see ResourceLoader#getClassLoader()
	 */
	@Nullable
	public final ResourceLoader getResourceLoader() {
		return this.reader.getResourceLoader();
	}

	/**
	 * Return the bean class loader to use, if any.
	 * <p>Note that this will be null in regular scenarios,
	 * as an indication to lazily resolve bean classes.
	 * @see XmlBeanDefinitionReader#setBeanClassLoader
	 */
	@Nullable
	public final ClassLoader getBeanClassLoader() {
		return this.reader.getBeanClassLoader();
	}

	/**
	 * Return the environment to use.
	 * @see XmlBeanDefinitionReader#setEnvironment
	 */
	public final Environment getEnvironment() {
		return this.reader.getEnvironment();
	}

	/**
	 * Return the namespace resolver.
	 * @see XmlBeanDefinitionReader#setNamespaceHandlerResolver
	 */
	public final NamespaceHandlerResolver getNamespaceHandlerResolver() {
		return this.namespaceHandlerResolver;
	}


	// Convenience methods to delegate to

	/**
	 * Call the bean name generator for the given bean definition.
	 * @see XmlBeanDefinitionReader#getBeanNameGenerator()
	 * @see org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName
	 */
	public String generateBeanName(BeanDefinition beanDefinition) {
		return this.reader.getBeanNameGenerator().generateBeanName(beanDefinition, getRegistry());
	}

	/**
	 * Call the bean name generator for the given bean definition
	 * and register the bean definition under the generated name.
	 * @see XmlBeanDefinitionReader#getBeanNameGenerator()
	 * @see org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName
	 * @see BeanDefinitionRegistry#registerBeanDefinition
	 */
	public String registerWithGeneratedName(BeanDefinition beanDefinition) {
		String generatedName = generateBeanName(beanDefinition);
		getRegistry().registerBeanDefinition(generatedName, beanDefinition);
		return generatedName;
	}

	/**
	 * Read an XML document from the given String.
	 * @see #getReader()
	 */
	public Document readDocumentFromString(String documentContent) {
		InputSource is = new InputSource(new StringReader(documentContent));
		try {
			return this.reader.doLoadDocument(is, getResource());
		}
		catch (Exception ex) {
			throw new BeanDefinitionStoreException("Failed to read XML document", ex);
		}
	}

}

XmlReaderContext主要就是保存了XmlBeanDefinitionReader和一个NamespaceHandlerResolver


这里我主要是想讲一下这个事件监听机制,所以来看一下其父类ReaderContext

代码语言:javascript
复制
public class ReaderContext {

	private final Resource resource;

	private final ProblemReporter problemReporter;
     
    //最多只有一个监听者
	private final ReaderEventListener eventListener;

	private final SourceExtractor sourceExtractor;


	/**
	 * Construct a new {@code ReaderContext}.
	 * @param resource the XML bean definition resource
	 * @param problemReporter the problem reporter in use
	 * @param eventListener the event listener in use
	 * @param sourceExtractor the source extractor in use
	 */
	public ReaderContext(Resource resource, ProblemReporter problemReporter,
			ReaderEventListener eventListener, SourceExtractor sourceExtractor) {

		this.resource = resource;
		this.problemReporter = problemReporter;
		this.eventListener = eventListener;
		this.sourceExtractor = sourceExtractor;
	}

	public final Resource getResource() {
		return this.resource;
	}


	// Errors and warnings

	/**
	 * Raise a fatal error.
	 */
	public void fatal(String message, @Nullable Object source) {
		fatal(message, source, null, null);
	}

	/**
	 * Raise a fatal error.
	 */
	public void fatal(String message, @Nullable Object source, @Nullable Throwable cause) {
		fatal(message, source, null, cause);
	}

	/**
	 * Raise a fatal error.
	 */
	public void fatal(String message, @Nullable Object source, @Nullable ParseState parseState) {
		fatal(message, source, parseState, null);
	}

	/**
	 * Raise a fatal error.
	 */
	public void fatal(String message, @Nullable Object source, @Nullable ParseState parseState, @Nullable Throwable cause) {
		Location location = new Location(getResource(), source);
		this.problemReporter.fatal(new Problem(message, location, parseState, cause));
	}

	/**
	 * Raise a regular error.
	 */
	public void error(String message, @Nullable Object source) {
		error(message, source, null, null);
	}

	/**
	 * Raise a regular error.
	 */
	public void error(String message, @Nullable Object source, @Nullable Throwable cause) {
		error(message, source, null, cause);
	}

	/**
	 * Raise a regular error.
	 */
	public void error(String message, @Nullable Object source, @Nullable ParseState parseState) {
		error(message, source, parseState, null);
	}

	/**
	 * Raise a regular error.
	 */
	public void error(String message, @Nullable Object source, @Nullable ParseState parseState, @Nullable Throwable cause) {
		Location location = new Location(getResource(), source);
		this.problemReporter.error(new Problem(message, location, parseState, cause));
	}

	/**
	 * Raise a non-critical warning.
	 */
	public void warning(String message, @Nullable Object source) {
		warning(message, source, null, null);
	}

	/**
	 * Raise a non-critical warning.
	 */
	public void warning(String message, @Nullable Object source, @Nullable Throwable cause) {
		warning(message, source, null, cause);
	}

	/**
	 * Raise a non-critical warning.
	 */
	public void warning(String message, @Nullable Object source, @Nullable ParseState parseState) {
		warning(message, source, parseState, null);
	}

	/**
	 * Raise a non-critical warning.
	 */
	public void warning(String message, @Nullable Object source, @Nullable ParseState parseState, @Nullable Throwable cause) {
		Location location = new Location(getResource(), source);
		this.problemReporter.warning(new Problem(message, location, parseState, cause));
	}


	// Explicit parse events

	/**
	 * Fire a defaults-registered event.
	 */
	public void fireDefaultsRegistered(DefaultsDefinition defaultsDefinition) {
		this.eventListener.defaultsRegistered(defaultsDefinition);
	}

	/**
	 * Fire a component-registered event.
	 */
	public void fireComponentRegistered(ComponentDefinition componentDefinition) {
		this.eventListener.componentRegistered(componentDefinition);
	}

	/**
	 * Fire an alias-registered event.
	 */
	public void fireAliasRegistered(String beanName, String alias, @Nullable Object source) {
		this.eventListener.aliasRegistered(new AliasDefinition(beanName, alias, source));
	}

	/**
	 * Fire an import-processed event.
	 */
	public void fireImportProcessed(String importedResource, @Nullable Object source) {
		this.eventListener.importProcessed(new ImportDefinition(importedResource, source));
	}

	/**
	 * Fire an import-processed event.
	 */
	public void fireImportProcessed(String importedResource, Resource[] actualResources, @Nullable Object source) {
		this.eventListener.importProcessed(new ImportDefinition(importedResource, actualResources, source));
	}


	// Source extraction

	/**
	 * Return the source extractor in use.
	 */
	public SourceExtractor getSourceExtractor() {
		return this.sourceExtractor;
	}

	/**
	 * Call the source extractor for the given source object.
	 */
	@Nullable
	public Object extractSource(Object sourceCandidate) {
		return this.sourceExtractor.extractSource(sourceCandidate, this.resource);
	}

}

主要有几点:错误记录,发布事件和原数据读取,下面也给出了这个ReaderEventListener 接口的源码和spring顶层监听器接口的源码,都比较简单,这里不多解释了

代码语言:javascript
复制
public interface ReaderEventListener extends EventListener {

	/**
	 * Notification that the given defaults has been registered.
	 */
	void defaultsRegistered(DefaultsDefinition defaultsDefinition);

	/**
	 * Notification that the given component has been registered.
	 */
	void componentRegistered(ComponentDefinition componentDefinition);

	/**
	 * Notification that the given alias has been registered.
	 */
	void aliasRegistered(AliasDefinition aliasDefinition);

	/**
	 * Notification that the given import has been processed.
	 */
	void importProcessed(ImportDefinition importDefinition);

}
代码语言:javascript
复制
public interface EventListener {
}

自定义监听器

这里监听器的实现可比其他的源码容易多了,下面给大家稍微演示一下:

代码语言:javascript
复制
public class MyXmlBeanFactory extends DefaultListableBeanFactory {
    private XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

    //原XmlBeanFactory这里的XmlBeanDefinitionReader 是私有的,我这里改了一下
    public MyXmlBeanFactory(Resource resource, ReaderEventListener readerEventListener) throws BeansException {
        this(resource, null,readerEventListener);
    }


    public MyXmlBeanFactory(Resource resource, BeanFactory parentBeanFactory,ReaderEventListener readerEventListener) throws BeansException {
        super(parentBeanFactory);
        this.reader.setEventListener(readerEventListener);
        this.reader.loadBeanDefinitions(resource);
    }

}

MyReaderEventListener 这里我就对BeanDefiniton创建完毕的事件进行处理

代码语言:javascript
复制
public class MyReaderEventListener implements ReaderEventListener {
    @Override
    public void defaultsRegistered(DefaultsDefinition defaultsDefinition) {

    }

    @Override
    public void componentRegistered(ComponentDefinition componentDefinition) {
        System.out.println("processBeanDefinition-->getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))");
        System.out.println("Bean的全类型如下: ");
        String beanClassName = componentDefinition.getBeanDefinitions()[0].getBeanClassName();
        System.out.println(beanClassName);
        System.out.println("调用Peo的show方法: ");
        try {
            Class<?> aClass = Class.forName(beanClassName);
            if(aClass.equals(Peo.class))
            {
                Peo peo = (Peo) aClass.newInstance();
                peo.show();
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void aliasRegistered(AliasDefinition aliasDefinition) {

    }

    @Override
    public void importProcessed(ImportDefinition importDefinition) {

    }
}

测试:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

懂了吗?

在这里插入图片描述
在这里插入图片描述

Alias标签的解析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我想各位可能都忘记了alias标签被解析的代码是在哪里被调用的了,现在我帮大家回忆一下:

代码语言:javascript
复制
	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);
		}
	}
代码语言:javascript
复制
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		//解析alias标签
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

DefaultBeanDefinitionDocumentReader#processAliasRegistration—>解析alias标签

代码语言:javascript
复制
	protected void processAliasRegistration(Element ele) {
	//获取beanName
		String name = ele.getAttribute(NAME_ATTRIBUTE);
	//获取alias	
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
			//注册别名---上面讲过了
			//getReaderContext在这里也被用到了
				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));
		}
	}
在这里插入图片描述
在这里插入图片描述

import标签的解析

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		//解析import标签
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

DefaultBeanDefinitionDocumentReader#importBeanDefinitionResource—>解析import标签

代码语言:javascript
复制
	protected void importBeanDefinitionResource(Element ele) {
	    //获取resource属性指定的资源路径
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		// Resolve system properties: e.g. "${user.dir}"
		//解析系统属性,例如"${user.dir}"
		//这里也用到了getReaderContext
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

		Set<Resource> actualResources = new LinkedHashSet<>(4);

		// Discover whether the location is an absolute or relative URI---判断资源路径是绝对路径还是相对路径
		boolean absoluteLocation = false;
		try {
			absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		}
		catch (URISyntaxException ex) {
			// cannot convert to an URI, considering the location relative
			// unless it is the well-known Spring prefix "classpath*:"
		}

		// Absolute or relative?
		//如果是绝对路径就直接加载配置文件
		if (absoluteLocation) {
			try {
			//getReaderContext().getReader()---->xmlBeanDefinition--->loadBeanDefinitions是不是又回到起点了
				int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
				if (logger.isTraceEnabled()) {
					logger.trace("Imported " + importCount + " bean definitions from URL location [" + location + "]");
				}
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error(
						"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
			}
		}
		else {
		//如果是相对路径
			// No URL -> considering resource location as relative to the current file.
			try {
				int importCount;
				//根据相对路径来定位资源
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				//如果资源存在就加载指定的配置文件
				if (relativeResource.exists()) {
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				else {
				//否则尝试使用传入的resource的url作为基础路径进行查找
					String baseLocation = getReaderContext().getResource().getURL().toString();
					importCount = getReaderContext().getReader().loadBeanDefinitions(
							StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]");
				}
			}
			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);
			}
		}
		//进行监听器激活处理
		Resource[] actResArray = actualResources.toArray(new Resource[0]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}
在这里插入图片描述
在这里插入图片描述

嵌入式Bean标签的解析

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse---把当前beans标签作为根节点从头循环一遍,个人认为这里还蛮有意思的
			doRegisterBeanDefinitions(ele);
		}
	}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring读源码系列02----默认标签解析过程
  • Bean标签的解析及注册
    • DefaultBeanDefinitionDocumentReader#processBeanDefinition----对Bean标签进行处理的方法
      • BeanDefinitionParserDelegate#parseBeanDefinitionElement从xml配置信息—>BeanDefinition
      • BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired---->对默认bean标签下的自定义配置进行解析
  • AbstractBeanDefinition属性
  • 解析默认标签中的自定义标签
  • 注册解析的BeanDefinition
    • DefaultBeanDefinitionDocumentReader#processBeanDefinition
      • BeanDefinitionReaderUtils.registerBeanDefinition---->注册解析的BeanDefinition
      • BeanDefinitionRegistry#registerBeanDefinition---->通过beanName注册BeanDefinition
      • SimpleAliasRegistry#registerAlias---->通过别名注册BeanDefinition
  • 通知监听器解析及注册完成
    • 补充说明—>ReaderContext
      • 自定义监听器
      • Alias标签的解析
        • DefaultBeanDefinitionDocumentReader#processAliasRegistration—>解析alias标签
        • import标签的解析
          • DefaultBeanDefinitionDocumentReader#importBeanDefinitionResource—>解析import标签
          • 嵌入式Bean标签的解析
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档