欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何利用Spring把元素解析成BeanDefinition對(duì)象

 更新時(shí)間:2022年08月31日 09:56:35   作者:石臻臻的雜貨鋪???????  
這篇文章主要介紹了如何利用Spring把元素解析成BeanDefinition對(duì)象,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

前言

spring中解析元素最重要的一個(gè)對(duì)象應(yīng)該就屬于 BeanDefinition了;這個(gè)Spring容器中最基本的內(nèi)部數(shù)據(jù)結(jié)構(gòu);它讓xml文件中所有的配置有了一個(gè)歸屬的地方;在xml中存在的配置都能在BeanDefinition找到對(duì)應(yīng)的屬性;我們今天來看看BeanDefinition是如何被創(chuàng)建的

1.BeanDefinition

Spring 容器中的內(nèi)部數(shù)據(jù)結(jié)構(gòu),是轉(zhuǎn)換為容器中bean實(shí)例的最小接口,其中包含了 屬性值、構(gòu)造函數(shù)的參數(shù)值等等;

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    /**
     * 作用域標(biāo)識(shí)符。
     */
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;   // singleton作用域
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;   // prototype作用域

    /**
     * 角色提示
     */
    int ROLE_APPLICATION = 0;   // 表明BeanDefinition是應(yīng)用程序的主要部分。通常對(duì)應(yīng)于用戶定義的Bean
    int ROLE_SUPPORT = 1;   // 表明BeanDefinition是支持大部分配置。通常是外部的ComponentDefinition
    int ROLE_INFRASTRUCTURE = 2;    // 表明BeanDefinition提供了一個(gè)完全后臺(tái)角色,與最終用戶無關(guān)。這個(gè)提示是在注冊(cè)bean時(shí)使用的,這些bean完全是組件定義的內(nèi)部工作的一部分
    /**
     * 獲取、設(shè)置該BeanDefinition的父Bean的名稱
     */
    String getParentName();     
    void setParentName(String parentName);
    /**
     * 獲取、設(shè)置當(dāng)前Bean的類名
     * 
     */
    String getBeanClassName();      // 注意:這并不一定是運(yùn)行時(shí)真正的類名,如果有一個(gè)子定義覆蓋/繼承父類的名稱。
    void setBeanClassName(String beanClassName);    // 注意:類名可以在bean工廠的后處理器中進(jìn)行修改,通常用它的解析變量替換原來的類名

    /**
     * 獲取、設(shè)置工廠Bean或工廠方法(如果有)
     */
    String getFactoryBeanName();
    void setFactoryBeanName(String factoryBeanName);
    String getFactoryMethodName();
    void setFactoryMethodName(String factoryMethodName);    // 注意:該方法由指定工廠Bean調(diào)用或者作為本地bean類的靜態(tài)方法

    /**
     * 獲取、設(shè)置當(dāng)前Bean的作用域或者為null(還不明確時(shí))
     */
    String getScope();
    void setScope(String scope);
    /**
     * 獲取、設(shè)置懶初始化
     */
    boolean isLazyInit();
    void setLazyInit(boolean lazyInit);
    /**
     * 獲取、設(shè)置該Bean所依賴的Bean名稱列表
     */
    String[] getDependsOn();
    void setDependsOn(String... dependsOn);
    /**
     * 獲取、設(shè)置該Bean是否為其他Bean自動(dòng)裝配的候選者
     */
    boolean isAutowireCandidate
    void setAutowireCandidate(boolean autowireCandidate);

    /**
     * 獲取、設(shè)置該Bean是否為自動(dòng)裝配的主要候選者
     */
    boolean isPrimary();
    void setPrimary(boolean primary);

    /**
     * 獲取該Bean的構(gòu)造器參數(shù)值
     */
    ConstructorArgumentValues getConstructorArgumentValues();
    /**
     * 獲取該Bean的可運(yùn)用于新實(shí)例的屬性值
     */
    MutablePropertyValues getPropertyValues();
    /**
     * 判斷該Bean是否為單例、原型、抽象Bean
     */
    boolean isSingleton();
    boolean isPrototype();
    boolean isAbstract();
    /**
     * 獲取該Bean所扮演的角色(ROLE_APPLICATION、ROLE_SUPPORT、ROLE_INFRASTRUCTURE)
     */
    int getRole();
    /**
     * 獲取該Bean、資源的可讀性描述
     */
    String getDescription();
    String getResourceDescription();
    /**
     * 獲取原始的BeanDefinition
     */
    BeanDefinition getOriginatingBeanDefinition();
}

2.BeanDefinitionParserDelegate

BeanDefinitionParserDelegate是一個(gè)非常重要的類;spring將所有的解析操作都委托給了這個(gè)類;所有我們今天分析 BeanDefinition的創(chuàng)建,都是在這個(gè)類里面;

那么我們進(jìn)一起進(jìn)入探個(gè)究竟把;創(chuàng)建BeanDefinition的入口

2.1.parseBeanDefinitionElement

	/**                     解析元素
	 *1.containingBean 還不清楚作用,回頭分析 TODO...
	 *2.解析 id,name屬性放入List<String> aliases中;aliases持有所有別名
	 *3.檢查beanName,和aliases是否跟之前有重復(fù);因?yàn)楫?dāng)前的對(duì)象BeanDefinitionParserDelegate中屬性 Set<String> usedNames 會(huì)持有所有解析出來的beanName 和 aliases;
	 *4.解析元素,將xml中的所有元素解析成AbstractBeanDefinition中對(duì)應(yīng)的屬性;
	 *5.解析完了拿到AbstractBeanDefinition的實(shí)例之后;創(chuàng)建一個(gè)BeanDefinitionHolder實(shí)例對(duì)象;
	    這個(gè)實(shí)例對(duì)象持有 AbstractBeanDefinition,beanName,aliases;這些屬性;并且返回holder實(shí)例對(duì)象;
	 */
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
		//獲取id
		String id = ele.getAttribute(ID_ATTRIBUTE);
		//獲取name屬性;例如:<bean id="simpleProducer" name="aliases1,;aliases2,;aliases3" > 這樣就設(shè)置了多個(gè)別名了
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		List<String> aliases = new ArrayList<String>();
		if (StringUtils.hasLength(nameAttr)) {
		//解析別名;上面的例子就解析成了  三個(gè)別名了aliases1,;aliases2,;aliases3
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}
		String beanName = id;
		//如果沒有設(shè)置id,但是設(shè)置了name ;那么就把name別名中的第一個(gè)當(dāng)做 bean的名字;并且從別名中remove掉
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isDebugEnabled()) {
				logger.debug("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}
		if (containingBean == null) {
			/**
			*檢查當(dāng)前的beanName是否唯一
			*1.先判斷this.usedNames 是否包含beanName(this.usedNames是一個(gè) set集合,專門保存所有的beanName)
			*2.如果this.usedNames不包含,再判斷當(dāng)前aliase是否已經(jīng)被set到this.usedNames集合中了;
			*3.如果上述beanName或者aliase中被發(fā)現(xiàn)已注冊(cè)則拋出異常,否則將beanName和aliase一起add到this.usedNames中去
			*4.就算beanName與別名aliase有重復(fù)也沒有關(guān)系,set會(huì)自動(dòng)去重
			*/
			checkNameUniqueness(beanName, aliases, ele);
		}
		/**
		*1.解析Element,返回解析后的對(duì)象 AbstractBeanDefinition;很多屬性例如:class、parent、scope、abstract、lazy-init、meta、lookup-method、replaced-method、constructor-arg、property、qualifier等;
		*2.這個(gè)beanName作為參數(shù)只是用作 異常信息記錄
		*3.看下文詳細(xì)
		*/
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			//如果沒有設(shè)置 id 也沒有設(shè)置name屬性;則spring生成一個(gè)beanName
			if (!StringUtils.hasText(beanName)) {
				try {
					//TODO... 這個(gè)containingBean還不知道是干啥用的
					if (containingBean != null) {
						//自動(dòng)生成beanName;生成規(guī)則我就不贅述了
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
					if (logger.isDebugEnabled()) {
						logger.debug("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);
			//
			/**
			*1.返回一個(gè)BeanDefinitionHolder對(duì)象,繼承子 implements BeanMetadataElement ;這個(gè)對(duì)象持有
			*   this.beanDefinition = beanDefinition;
				this.beanName = beanName;
				this.aliases = aliases;
			*/
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

2.2.parseBeanDefinitionElement

	/**
	 * 解析bean definition ,不包括名稱或別名(因?yàn)樯厦嬉呀?jīng)解析過名稱和別名了),當(dāng)解析異常的時(shí)候回返回null;
	 * 返回的是一個(gè)GenericBeanDefinition對(duì)象
	 */
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, BeanDefinition containingBean) {
		/**
		* 1.BeanEntry是一個(gè) bean的實(shí)體類,它implements了 ParseState.Entry接口;Entry是一個(gè)標(biāo)志接口,什么都沒有做;
		* BeanEntry 只有一個(gè)private String beanDefinitionName;屬性
		* 2.ParseState類里面有一個(gè)private final Stack<Entry> state;棧;存放的對(duì)象類型是 Entry
		* 3.ParseState簡(jiǎn)單的棧結(jié)構(gòu)來跟蹤邏輯位置中解析過程,主要是記錄異常信息;在異常的時(shí)候 Spring調(diào)用error方法,會(huì)把ParseState棧中的信息一起拋出
		*/
		this.parseState.push(new BeanEntry(beanName));
		//獲取element中有 class屬性;
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}

		try {
			//獲取parent屬性
			String parent = null;
			if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
				parent = ele.getAttribute(PARENT_ATTRIBUTE);
			}
			/**
			*1.AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable ;它實(shí)現(xiàn)了部分BeanDefinition;
			*2.實(shí)現(xiàn)上創(chuàng)建的是一個(gè)GenericBeanDefinition對(duì)象;這個(gè)對(duì)象繼承了AbstractBeanDefinition;并且新增了屬性private String parentName;還實(shí)現(xiàn)了cloneBeanDefinition()等方法
			*3.父類類名路徑,自身全類名路徑,和當(dāng)前XmlReaderContext的類加載器為參數(shù)創(chuàng)建 AbstractBeanDefinition
				return BeanDefinitionReaderUtils.createBeanDefinition(
				parentName, className, this.readerContext.getBeanClassLoader());
			*4.如果ClassLoader為null;則 bd.setBeanClassName(className);設(shè)置全類名路徑;
			*  如果不為null;則bd.setBeanClass(ClassUtils.forName(className, classLoader));直接利用反射得到類的Class類型;最種調(diào)用的是 ClassLoader.loadClass(name)
			*/
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			/**
			*1.解析 <bean >里面的所有屬性值;例如:scope,abstract,lazy-init,autowire,primary,depends-on等
			*2.所有的屬性都設(shè)置到了 AbstractBeanDefinition bd中
			*/
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			//設(shè)置description值;例如<description>test</description>
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
			/**
			*1.解析元數(shù)據(jù) Meta; Meta在Element中是 <meta key="test" value="testvalue" ></meta>
			*2.方法參數(shù)類型是 BeanMetadataAttributeAccessor;bd是有繼承BeanMetadataAttributeAccessor的;
			*3.解析了meta中的key和value;放入到BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);然后bd調(diào)用attributeAccessor.addMetadataAttribute(attribute);就不meta元數(shù)據(jù)放入到bd中去了;
			*/
			parseMetaElements(ele, bd);
			/**
			*重寫特定的方法返回 指定 的實(shí)例對(duì)象
			*1.Spring有一種機(jī)制,可以動(dòng)態(tài)的實(shí)現(xiàn)或重寫bean容器中指定bean的指定方法,然后將返回值指定為bean容器中的另一個(gè)bean
			*2.使用的時(shí)候 
				<bean id="beanB" class="com.app.BeanB" scope="prototype"/>
					<bean id="beanA" class="com.app.BeanA">
					<!-- 表示將由Spring重寫getBeanB()方法,并返回名為beanB的bean -->
					<lookup-method name="getBeanB" bean="beanB"/>
				</bean>
			*3.bd中的屬性private MethodOverrides methodOverrides = new MethodOverrides();專門存放這個(gè)
			*4.解析到bd中 
				LookupOverride override = new LookupOverride(methodName, beanRef);
				override.setSource(extractSource(ele));
				overrides.addOverride(override);
			
			*5.詳細(xì):[這里寫鏈接內(nèi)容](https://blog.csdn.net/elim168/article/details/74939012)
			*/
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			/**
			*1.跟上面類似
			*2.replaced method注入是spring動(dòng)態(tài)改變bean里方法的實(shí)現(xiàn)。需要改變的方法,使用spring內(nèi)原有其他類(需要繼承接口org.springframework.beans.factory.support.MethodReplacer)的邏輯,替換這個(gè)方法。通過改變方法執(zhí)行邏輯來動(dòng)態(tài)改變方法。內(nèi)部實(shí)現(xiàn)為使用cglib方法,重新生成子類,重寫配置的方法和返回對(duì)象,達(dá)到動(dòng)態(tài)改變的效果。
			3.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.addOverride(replaceOverride);
				
			*/
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
			//
			/**
			*1.解析構(gòu)造函數(shù)中的參數(shù) constructor-arg;放入bd中的 ConstructorArgumentValues constructorArgumentValues屬性中Map<Integer, ValueHolder> indexedArgumentValues map中;
			*2.解析的是 <constructor-arg index="0" value="1" />這種的
			*/
			parseConstructorArgElements(ele, bd);
			/**
			*1.set方法注入的處理(比較常用的注入);格式是<property name="application" value="${myApplicationCode}"/>
			*2.與上面的構(gòu)造函數(shù)不一樣的是;這里解析出來的值是個(gè)PropertyValue對(duì)象
			*3.show the code
				//解析出來屬性值
				Object val = parsePropertyValue(ele, bd, propertyName);
				//構(gòu)造PropertyValue實(shí)例
				PropertyValue pv = new PropertyValue(propertyName, val);
				//解析元數(shù)據(jù) meta數(shù)據(jù) ;屬性下也可以配置meta
				![meta](https://img-blog.csdn.net/20180507143039501?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTA2MzQwNjY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
				parseMetaElements(ele, pv);
				pv.setSource(extractSource(ele));
				//將PropertyValue設(shè)置到bd的MutablePropertyValues propertyValues;屬性中;
				bd.getPropertyValues().addPropertyValue(pv);
			*/
			parsePropertyElements(ele, bd);
			/**
			*1.解析qualifier元素;存放在 Map<String, AutowireCandidateQualifier> qualifiers
			*/
			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;
	}

2.3 parseBeanDefinitionAttributes

	 //解析bean的屬性值
	public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			BeanDefinition containingBean, AbstractBeanDefinition bd) {
		/**singleton 屬性是1.x的時(shí)候的東西,現(xiàn)在已經(jīng)廢棄,用scope代替了;例如 scope="singleton"**/
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		/**
		*設(shè)置作用域;private String scope = SCOPE_DEFAULT;是AbstractBeanDefinition中的屬性,默認(rèn)是 "" ;
		*/
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}
		/** 這個(gè)containingBean 暫時(shí)不清楚作用,等會(huì)分析 TODO.. **/
		else if (containingBean != null) {
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
		}
		//設(shè)置 abstract屬性,默認(rèn)是 false
		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}
		//如果當(dāng)前元素沒有設(shè)置 lazyInit 懶加載;則去 this.defaults.getLazyInit();這個(gè)defaults是上一篇分析過的;整個(gè)xml文件全局的默認(rèn)值;
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		if (DEFAULT_VALUE.equals(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
		// 設(shè)置注入方式,有 byName byType 等等,如果當(dāng)前沒有設(shè)置,則取this.defaults.getAutowire()的值;
		//然后將其轉(zhuǎn)換為對(duì)應(yīng)的int類型;例如byName是int AUTOWIRE_BY_NAME = 1;
		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		bd.setAutowireMode(getAutowireMode(autowire));
		//這個(gè)dependency-check字面意義是依賴檢查的類型;具體一會(huì)分析;如果當(dāng)前沒有設(shè)置,則取this.defaults.getDependencyCheck()的值;TODO...
		String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
		bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
		/**
		* 1.設(shè)置depends-on屬性;
		* 2.depends-on="commonService,;redisComponent"可以用 ,;來設(shè)置多個(gè);所以AbstractBeanDefinition中的dependsOn是一個(gè)數(shù)組類型
		* 3.depends-on是指指定Bean初始化及銷毀時(shí)的順序,使用depends-on屬性指定的Bean要先初始化完畢后才初始化當(dāng)前Bean
		*/
		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
		}
		//這個(gè)autowireCandidate不是很清楚  回頭分析TODo..
		String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
		if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
			String candidatePattern = this.defaults.getAutowireCandidates();
			if (candidatePattern != null) {
				String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
				bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
			}
		}
		else {
			bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
		}
		//設(shè)置primary 裝配時(shí)當(dāng)出現(xiàn)多個(gè)Bean候選者時(shí),被標(biāo)記為Primary的Bean將作為首選者,否則將拋出異常 ;默認(rèn)為false
		//https://blog.csdn.net/qq_16055765/article/details/78833260
		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
		}
		//設(shè)置初始化方法
		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			if (!"".equals(initMethodName)) {
				bd.setInitMethodName(initMethodName);
			}
		}
		else {
			//如果 當(dāng)前元素沒有設(shè)置 init_method 屬性,則判斷 xml全局配置有沒有設(shè)置;this.defaults是全局設(shè)置
			if (this.defaults.getInitMethod() != null) {
				bd.setInitMethodName(this.defaults.getInitMethod());
				bd.setEnforceInitMethod(false);
			}
		}
		//與上面初始化無二
		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);
			}
		}
		//設(shè)置factoryMethodName; spring通過工廠方法配置Bean
		//https://blog.csdn.net/mrwuyi/article/details/51578654
		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
		}
		//設(shè)置factoryBeanName   spring通過工廠方法配置Bean
		//https://blog.csdn.net/mrwuyi/article/details/51578654
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
		}

		return bd;
	}

2.4 parseConstructorArgElement

	/**
	 * 解析 構(gòu)造函數(shù)的參數(shù)
	 */
	public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		//如果xml配置了index
		if (StringUtils.hasLength(indexAttr)) {
			try {
				int index = Integer.parseInt(indexAttr);
				if (index < 0) {
					error("'index' cannot be lower than 0", ele);
				}
				else {
					try {
						/**
						*1.構(gòu)造參數(shù)實(shí)體類繼承子ParseState.Entry ConstructorArgumentEntry implements ParseState.Entry;有個(gè)int index;屬性
						*2.上面解析beanName和aliaes的時(shí)候也有個(gè)BeanEntry實(shí)體類繼承自ParseState.Entry,它有個(gè)屬性是beanDefinitionName
						*3.同樣的,將這個(gè)實(shí)體類push到 parseState中存放;
						*/
						this.parseState.push(new ConstructorArgumentEntry(index));
							/**
							 * Get the value of a property element. May be a list etc.
							 * Also used for constructor arguments, "propertyName" being null in this case.
							 * 獲取屬性值
							 */
						Object value = parsePropertyValue(ele, bd, null);
						//新建一個(gè)ValueHolder實(shí)例,這個(gè)專門存放構(gòu)造參數(shù)的一些 屬性值的
						ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
						//設(shè)置類型
						if (StringUtils.hasLength(typeAttr)) {
							valueHolder.setType(typeAttr);
						}
						//設(shè)置name
						if (StringUtils.hasLength(nameAttr)) {
							valueHolder.setName(nameAttr);
						}
						valueHolder.setSource(extractSource(ele));
						//驗(yàn)證index是否設(shè)置正確
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
						//ConstructorArgumentValues有個(gè) Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<Integer, ValueHolder>(0)來hold參數(shù)
							bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
						}
					}
					finally {
						//出棧;簡(jiǎn)單的棧結(jié)構(gòu)來跟蹤邏輯位置中解析過程,主要是記錄異常信息的吧
						this.parseState.pop();
					}
				}
			}
			catch (NumberFormatException ex) {
				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
			}
		}
		else {
			try {
				//與上無二
				this.parseState.push(new ConstructorArgumentEntry());
				Object value = parsePropertyValue(ele, bd, null);
				ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
				if (StringUtils.hasLength(typeAttr)) {
					valueHolder.setType(typeAttr);
				}
				if (StringUtils.hasLength(nameAttr)) {
					valueHolder.setName(nameAttr);
				}
				valueHolder.setSource(extractSource(ele));
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
			}
			finally {
				this.parseState.pop();
			}
		}
	}

再著重分析一下Object value = parsePropertyValue(ele, bd, null);

解析屬性值,解析property 或者 constructor-arg;如下:

    <bean class="src.HelloWorld">
    <property name="beanA" ref="beanA" />
    <property name="name" value="姓名" />
    <constructor-arg name="a" value="1" />
    <constructor-arg name="list">
      <list>
        <value>1</value>
        <value>2</value>
        <value>3</value>
      </list>
    </constructor-arg>
    <meta key="meta1" value="meta1value"/>
  </bean>
  • 這個(gè)方法只有兩個(gè)地方調(diào)用 ①.解析屬性property元素的時(shí)候parsePropertyValue(ele, bd, propertyName) ②.解析構(gòu)造參數(shù)constructor-arg元素的時(shí)候 parsePropertyValue(ele, bd, null)
  • 檢查配置是否正確 最多只能有其中一個(gè)元素:ref,value,子元素(ref,value,list,set array 等等形式的元素) ;
  • 解析子元素,ref,value,list,set array.....等等
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
		String elementName = (propertyName != null) ?
						"<property> element for property '" + propertyName + "'" :
						"<constructor-arg> element";

		// 最多只能有其中一個(gè)元素:ref,value,子元素(ref,value,list,set array 等等形式的元素) 等等
		/**
		*<constructor-arg name="a" >
	    *<value >1</value>
	    *</constructor-arg>
		*/
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		/**如果寫法是下面這樣的嵌套子元素的話 就要進(jìn)入parsePropertySubElement解析嵌套子元素了
		*<constructor-arg name="a" >
	    *<value >1</value>
	    *</constructor-arg>
		*/
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
					!nodeNameEquals(node, META_ELEMENT)) {
				// Child element is what we're looking for.
				if (subElement != null) {
					error(elementName + " must not contain more than one sub-element", ele);
				}
				else {
					subElement = (Element) node;
				}
			}
		}
		
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
		//1.如果 ref 和 value都存在  拋異常
		//2.如果ref或者value存在 一個(gè)并且 subElement也存在  拋異常
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null)) {
			error(elementName +
					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}

//如果是ref;返回RuntimeBeanReference implements BeanReference;有beanName,toParent,source等屬性
		if (hasRefAttribute) {
			String refName = ele.getAttribute(REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(ele));
			return ref;
		}
		//如果是value;返回TypedStringValue;設(shè)置屬性 value和source 
		else if (hasValueAttribute) {
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}
		//如果是list;解析一下子元素
		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;
		}
	}
//解析子元素
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
		//如果不是默認(rèn)的命名空間,則最終調(diào)用public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) 來解析;
		//第一篇文章分析過 根據(jù)元素選擇不同的解析器來解析;
		if (!isDefaultNamespace(ele)) {
			return parseNestedCustomElement(ele, bd);
		}
		//解析<bean>元素;這里就是我們本文正在分析的方法,所以不概述了
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
			if (nestedBd != null) {
				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
			}
			return nestedBd;
		}
		//如果是ref 元素 RuntimeBeanReference
		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;
			if (!StringUtils.hasLength(refName)) {
				// A reference to the id of another bean in the same XML file.
				refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
				if (!StringUtils.hasLength(refName)) {
					// A reference to the id of another bean in a parent context.
					refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
					toParent = true;
					if (!StringUtils.hasLength(refName)) {
						error("'bean', 'local' 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 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)) {
			/**解析 下面這種形式的
			* <constructor-arg name="a" >
		    *       <value  type="java.lang.Integer"  >1</value>
			* </constructor-arg>
		    * <property name="name">
			*      <value   >姓名</value>
		    * </property>
		    * 1.如果沒有設(shè)置type屬性,則返回new TypedStringValue(value);SpecifiedTypeName是空串;
		    * 2.如果設(shè)置了type,再判斷當(dāng)前readerContext是否有ClassLoader,如果有,則利用反射生成targetTypeName類型的 Class對(duì)象;再返回new TypedStringValue(value, targetType);這個(gè)targetType就是Class對(duì)象
		    * 3.否則的話,返回new TypedStringValue(value, targetTypeName);targetType就是全類名路徑
			*/
			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;
		}
	}

3 總結(jié)

至此,BeanDefinition就已經(jīng)解析完成了! 我們一起總結(jié)一下整個(gè)流程:

  • 解析 id,name屬性放入List aliases中;aliases持有所有別名
  • 檢查beanName,和aliases是否跟之前有重復(fù);因?yàn)楫?dāng)前的對(duì)象BeanDefinitionParserDelegate中屬性 Set usedNames 會(huì)持有所有解析出來的beanName 和 aliases;
  • 解析元素,將xml中的所有元素解析成AbstractBeanDefinition中對(duì)應(yīng)的屬性;
  • 解析完了拿到AbstractBeanDefinition的實(shí)例之后;創(chuàng)建一個(gè)BeanDefinitionHolder實(shí)例對(duì)象; 這個(gè)實(shí)例對(duì)象持有 AbstractBeanDefinition,beanName,aliases;這些屬性;并且返回holder實(shí)例對(duì)象;

到此這篇關(guān)于如何利用Spring把元素解析成BeanDefinition對(duì)象的文章就介紹到這了,更多相關(guān)Spring BeanDefinition內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 通過springboot+mybatis+druid配置動(dòng)態(tài)數(shù)據(jù)源

    通過springboot+mybatis+druid配置動(dòng)態(tài)數(shù)據(jù)源

    這篇文章主要介紹了通過springboot+mybatis+druid配置動(dòng)態(tài)數(shù)據(jù)源,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下
    2019-06-06
  • Spring Boot之過濾器 Filter注入的方式解析

    Spring Boot之過濾器 Filter注入的方式解析

    這篇文章主要介紹了Spring Boot之過濾器 Filter注入的方式解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 使用@JsonFormat和@DateTimeFormat對(duì)Date格式化操作

    使用@JsonFormat和@DateTimeFormat對(duì)Date格式化操作

    這篇文章主要介紹了使用@JsonFormat和@DateTimeFormat對(duì)Date格式化操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 一篇文章帶你入門Java修飾符

    一篇文章帶你入門Java修飾符

    Java語言提供了很多修飾符,主要分為以下兩類:訪問修飾符;非訪問修飾符。修飾符用來定義類、方法或者變量,通常放在語句的最前端。我們通過下面的例子來說明,下面就跟小編一起來看下吧
    2021-08-08
  • Mybatis批處理、Mysql深分頁操作

    Mybatis批處理、Mysql深分頁操作

    這篇文章主要介紹了Mybatis批處理、Mysql深分頁操作,Mybatis批量操作包括Foreach方式和ExecutorType.BATCH插入操作,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • Spring Boot線程池使用的一些實(shí)用心得

    Spring Boot線程池使用的一些實(shí)用心得

    理論上線程越多程序可能更快,但在實(shí)際使用中我們需要考慮到線程本身的創(chuàng)建以及銷毀的資源消耗,以及保護(hù)操作系統(tǒng)本身的目的我們通常需要將線程限制在一定的范圍之類,這篇文章主要給大家介紹了關(guān)于Spring Boot線程池使用的一些實(shí)用心得,需要的朋友可以參考下
    2021-09-09
  • Java Mybatis一級(jí)緩存和二級(jí)緩存

    Java Mybatis一級(jí)緩存和二級(jí)緩存

    緩存是內(nèi)存當(dāng)中一塊存儲(chǔ)數(shù)據(jù)的區(qū)域,目的是提高查詢效率,降低服務(wù)器和數(shù)據(jù)庫的壓力,這篇文章主要介紹了Mybatis一級(jí)緩存和二級(jí)緩存,感興趣的同學(xué)可以參考閱讀本文
    2023-04-04
  • Springboot啟動(dòng)原理詳細(xì)講解

    Springboot啟動(dòng)原理詳細(xì)講解

    這篇文章主要介紹了SpringBoot啟動(dòng)原理的分析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • maven國(guó)內(nèi)鏡像配置的方法步驟

    maven國(guó)內(nèi)鏡像配置的方法步驟

    這篇文章主要介紹了maven國(guó)內(nèi)鏡像配置的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java代碼注釋規(guī)范(動(dòng)力節(jié)點(diǎn)整理)

    Java代碼注釋規(guī)范(動(dòng)力節(jié)點(diǎn)整理)

    代碼注釋是架起程序設(shè)計(jì)者與程序閱讀者之間的通信橋梁,最大限度的提高團(tuán)隊(duì)開發(fā)合作效率。也是程序代碼可維護(hù)性的重要環(huán)節(jié)之一。下面通過本文說一下我們?cè)谌粘i_發(fā)中使用的代碼注釋規(guī)范
    2017-03-03

最新評(píng)論