日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring源码解析五

發(fā)布時(shí)間:2025/5/22 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring源码解析五 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

1.創(chuàng)建用于承載屬性的BeanDefinition

這是一個(gè)接口,在spring中存在三種實(shí)現(xiàn):RootBeanDefinition,ChildBeanDefinition以及GenericBeanDefinition,三種實(shí)現(xiàn)繼承了AbsartBeanDefinition.

BeanDefinition是配置文件<bean>元素標(biāo)簽在容器中的內(nèi)部實(shí)現(xiàn),并將這些BeanDefinition注冊(cè)到BeanDefinitonRegistry中。BeanDefinitionRegistry是配置信息的內(nèi)存數(shù)據(jù)庫,主要是以Map的形式保存,后續(xù)操作直接從BeanDefinitionRegisry中讀取配置信息。

?

?

protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)

??????? ??? throws ClassNotFoundException {

?

??????? return BeanDefinitionReaderUtils.createBeanDefinition(

??????????????? parentName, className, this.readerContext.getBeanClassLoader());

??? }

public class BeanDefinitionReaderUtils {}

public static AbstractBeanDefinition createBeanDefinition(

??????????? String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {

?

??????? 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;

}

2.解析各種屬性

parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

對(duì)element的所有屬性進(jìn)行解析

??? /**

??? ?* 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,

??????????? BeanDefinition containingBean, AbstractBeanDefinition bd) {

?

??????? 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) {

??????????? // Take default from containing bean in case of an inner bean definition.

??????????? bd.setScope(containingBean.getScope());

??????? }

?

??????? if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {

??????????? bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));

??????? }

?

??????? String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);

??????? if (DEFAULT_VALUE.equals(lazyInit)) {

??????????? lazyInit = this.defaults.getLazyInit();

??????? }

??????? bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

?

??????? String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);

??????? bd.setAutowireMode(getAutowireMode(autowire));

?

??????? if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {

??????????? String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);

??????????? bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));

??????? }

?

??????? 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));

??????? }

?

??????? if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {

??????????? bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));

??????? }

?

??????? if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {

??????????? String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);

??????????? if (!"".equals(initMethodName)) {

??????????????? bd.setInitMethodName(initMethodName);

??????????? }

??????? }

??????? else {

??????????? if (this.defaults.getInitMethod() != null) {

??????????????? bd.setInitMethodName(this.defaults.getInitMethod());

??????????????? bd.setEnforceInitMethod(false);

??????????? }

??????? }

?

??????? 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);

??????????? }

??????? }

?

??????? if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {

??????????? bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));

??????? }

??????? if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {

??????????? bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));

??????? }

?

??????? return bd;

}

3解析子元素meta

<bean id=”myTestBean” class=”bean.MyTestBean”>

?? <met key=”testStr” value=”aaaa”/>

</bean>

對(duì)meta屬性的解析代碼如下:

?

public AbstractBeanDefinition parseBeanDefinitionElement(

??????????? Element ele, String beanName, BeanDefinition containingBean) {

?

??????? this.parseState.push(new BeanEntry(beanName));

?

??????? String className = null;

??????? if (ele.hasAttribute(CLASS_ATTRIBUTE)) {

??????????? className = ele.getAttribute(CLASS_ATTRIBUTE).trim();

??????? }

?

??????? try {

??????????? String parent = null;

??????????? if (ele.hasAttribute(PARENT_ATTRIBUTE)) {

??????????????? parent = ele.getAttribute(PARENT_ATTRIBUTE);

??????????? }

??????????? AbstractBeanDefinition bd = createBeanDefinition(className, parent);

?

??????????? parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

??????????? bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

?

??????????? parseMetaElements(ele, bd);

??????????? parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

??????????? parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

?

??????????? parseConstructorArgElements(ele, bd);

??????????? parsePropertyElements(ele, bd);

??????????? 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;

?? }

?

??? public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {

??????? NodeList nl = ele.getChildNodes();

??????? for (int i = 0; i < nl.getLength(); i++) {

??????????? Node node = nl.item(i);

??????????? if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {

??????????????? Element metaElement = (Element) node;

??????????????? String key = metaElement.getAttribute(KEY_ATTRIBUTE);

??????????????? String value = metaElement.getAttribute(VALUE_ATTRIBUTE);

??????????????? BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);

??????????????? attribute.setSource(extractSource(metaElement));

??????????????? attributeAccessor.addMetadataAttribute(attribute);

??????????? }

??????? }

?????? }

?

1.? 解析子元素lookup-mehtod

獲取器注入

是一種特殊的方法注入,它是把一個(gè)方法聲明為返回某種類型的bean,但實(shí)際上返回的bean在配置文件里面配置的,此方法可用在設(shè)計(jì)有插拔的功能上,解除程序依賴。Exception in thread "main" java.lang.NoClassDefFoundError: org/spriCaused by: java.lang.ClassNotFoundException: org.springframework.expression.ParserContextngframework/expression/ParserContext

當(dāng)業(yè)務(wù)發(fā)生變化時(shí),如何替換業(yè)務(wù)邏輯呢

實(shí)現(xiàn)新的業(yè)務(wù)邏輯,注冊(cè)到xmlbean中

?

提取源碼屬性

/**

??? ?* Parse lookup-override sub-elements of the given bean element.

??? ?*/

??? public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {

??????? NodeList nl = beanEle.getChildNodes();

??????? for (int i = 0; i < nl.getLength(); i++) {

??????????? Node node = nl.item(i);

??????????? if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {

??????????????? Element ele = (Element) node;

??????????????? String methodName = ele.getAttribute(NAME_ATTRIBUTE);

??????????????? String beanRef = ele.getAttribute(BEAN_ELEMENT);

??????????????? LookupOverride override = new LookupOverride(methodName, beanRef);

??????????????? override.setSource(extractSource(ele));

??????????????? overrides.addOverride(override);

??????????? }

??????? }

?? }

解析子元素replaced-method

這個(gè)方法是針對(duì)bean中replaced-method子元素的提取

方法替換:可以在運(yùn)行時(shí)用新的方法替換現(xiàn)有的方法,replaced-method不但可以動(dòng)態(tài)替換返回實(shí)體bean,而且還能動(dòng)態(tài)地更改原有方法的邏輯

<replacedMethod>的提取過程

??? /**

??? ?* 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)) {

??????????????? Element replacedMethodEle = (Element) node;

??????????????? String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);

??????????????? String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);

??????????????? 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);

??????????? }

??????? }

?????? }

?

解析子元素constructor-arg

/**

??? ?* Parse constructor-arg sub-elements of the given bean element.

??? ?*/

??? public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {

??????? NodeList nl = beanEle.getChildNodes();

??????? for (int i = 0; i < nl.getLength(); i++) {

??????????? Node node = nl.item(i);

??????????? if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {

??????????????? parseConstructorArgElement((Element) node, bd);

??????????? }

??????? }

?????? }

?

??? /**

??? ?* Parse a constructor-arg element.

??? ?*/

??? 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);

??????? 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));

??????????????????????? 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));

??????????????????????? if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {

??????????????????????????? error("Ambiguous constructor-arg entries for index " + index, ele);

??????????????????????? }

??????????????????????? else {

??????????????????????????? bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);

??????????????????????? }

??????????????????? }

??????????????????? finally {

??????????????????????? this.parseState.pop();

??????????????????? }

??????????????? }

??????????? }

??????????? catch (NumberFormatException ex) {

??????????????? error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);

??????????? }

??????? }

??????? else {

??????????? try {

??????????????? 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();

??????????? }

??????? }

?????? }

?

?

?

??? /**

??? ?* Get the value of a property element. May be a list etc.

??? ?* Also used for constructor arguments, "propertyName" being null in this case.

??? ?*/

??? public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {

??????? String elementName = (propertyName != null) ?

??????????????????????? "<property> element for property '" + propertyName + "'" :

??????????????????????? "<constructor-arg> element";

?

??????? // 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);

??????????? 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);

??????? if ((hasRefAttribute && hasValueAttribute) ||

??????????????? ((hasRefAttribute || hasValueAttribute) && subElement != null)) {

??????????? error(elementName +

??????????????????? " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);

??????? }

?

??????? if (hasRefAttribute) {

??????????? String refName = ele.getAttribute(REF_ATTRIBUTE);

??????????? if (!StringUtils.hasText(refName)) {

??????????????? error(elementName + " contains empty 'ref' attribute", ele);

??????????? }

??????????? RuntimeBeanReference ref = new RuntimeBeanReference(refName);

??????????? ref.setSource(extractSource(ele));

??????????? return ref;

??????? }

??????? else if (hasValueAttribute) {

??????????? 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;

??????? }

??? }

?

?

public Object parsePropertySubElement(Element ele, BeanDefinition bd) {

??????? return parsePropertySubElement(ele, bd, null);

?????? }

?

public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {

??????? if (!isDefaultNamespace(ele)) {

??????????? return parseNestedCustomElement(ele, bd);

??????? }

??????? else if (nodeNameEquals(ele, BEAN_ELEMENT)) {

??????????? BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);

??????????? if (nestedBd != null) {

??????????????? nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);

??????????? }

??????????? return nestedBd;

??????? }

??????? 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 a parent context.

??????????????? 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 ref = new RuntimeBeanReference(refName, toParent);

??????????? ref.setSource(extractSource(ele));

??????????? return ref;

??????? }

??????? else if (nodeNameEquals(ele, IDREF_ELEMENT)) {

??????????? return parseIdRefElement(ele);

??????? }

??????? else if (nodeNameEquals(ele, VALUE_ELEMENT)) {

??????????? return parseValueElement(ele, defaultValueType);

??????? }

??????? 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;

??????? }

??????? else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {

??????????? return parseArrayElement(ele, bd);

??????? }

??????? else if (nodeNameEquals(ele, LIST_ELEMENT)) {

??????????? return parseListElement(ele, bd);

??????? }

??????? else if (nodeNameEquals(ele, SET_ELEMENT)) {

??????????? return parseSetElement(ele, bd);

??????? }

??????? else if (nodeNameEquals(ele, MAP_ELEMENT)) {

??????????? return parseMapElement(ele, bd);

??????? }

??????? else if (nodeNameEquals(ele, PROPS_ELEMENT)) {

??????????? return parsePropsElement(ele);

??????? }

??????? else {

??????????? error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);

??????????? return null;

??????? }

?????? }

public class BeanDefinitionParserDelegate{}

解析子元素property

??? /**

??? ?* 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)) {

??????????????? parsePropertyElement((Element) node, bd);

??????????? }

??????? }

?????? }

將返回值使用PropertyValue進(jìn)行封裝,記錄在BeanDefinitionproertyValues屬性中。

?

解析子元素qualifier

?

??? /**

??? ?* Parse a qualifier element.

??? ?*/

??? public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {

??????? 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));

??????????? 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);

??????????????? 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;

??????????????????? }

??????????????? }

??????????? }

??????????? bd.addQualifier(qualifier);

??????? }

??????? finally {

??????????? this.parseState.pop();

??????? }

?????? }

轉(zhuǎn)載于:https://my.oschina.net/iioschina/blog/830899

總結(jié)

以上是生活随笔為你收集整理的spring源码解析五的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。