Spring BeanDefinitionParserDelegate

  • Author: HuiFer
  • 源码阅读仓库: SourceHot-spring

  • 全路径org.springframework.beans.factory.xml.BeanDefinitionParserDelegate

  • 解析 xml 中标签的委托类

  • 在这个类中定义常量如下,为后续解析提供帮助

  1. public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
  2. public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";
  3. public static final String TRUE_VALUE = "true";
  4. public static final String FALSE_VALUE = "false";
  5. public static final String DEFAULT_VALUE = "default";
  6. public static final String DESCRIPTION_ELEMENT = "description";
  7. public static final String AUTOWIRE_NO_VALUE = "no";
  8. public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
  9. public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
  10. public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";
  11. public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";
  12. public static final String NAME_ATTRIBUTE = "name";
  13. public static final String BEAN_ELEMENT = "bean";
  14. public static final String META_ELEMENT = "meta";
  15. public static final String ID_ATTRIBUTE = "id";
  16. public static final String PARENT_ATTRIBUTE = "parent";
  17. public static final String CLASS_ATTRIBUTE = "class";
  18. public static final String ABSTRACT_ATTRIBUTE = "abstract";
  19. public static final String SCOPE_ATTRIBUTE = "scope";
  20. public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";
  21. public static final String AUTOWIRE_ATTRIBUTE = "autowire";
  22. public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate";
  23. public static final String PRIMARY_ATTRIBUTE = "primary";
  24. public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";
  25. public static final String INIT_METHOD_ATTRIBUTE = "init-method";
  26. public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";
  27. public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";
  28. public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean";
  29. public static final String CONSTRUCTOR_ARG_ELEMENT = "constructor-arg";
  30. public static final String INDEX_ATTRIBUTE = "index";
  31. public static final String TYPE_ATTRIBUTE = "type";
  32. public static final String VALUE_TYPE_ATTRIBUTE = "value-type";
  33. public static final String KEY_TYPE_ATTRIBUTE = "key-type";
  34. public static final String PROPERTY_ELEMENT = "property";
  35. public static final String REF_ATTRIBUTE = "ref";
  36. public static final String VALUE_ATTRIBUTE = "value";
  37. public static final String LOOKUP_METHOD_ELEMENT = "lookup-method";
  38. public static final String REPLACED_METHOD_ELEMENT = "replaced-method";
  39. public static final String REPLACER_ATTRIBUTE = "replacer";
  40. public static final String ARG_TYPE_ELEMENT = "arg-type";
  41. public static final String ARG_TYPE_MATCH_ATTRIBUTE = "match";
  42. public static final String REF_ELEMENT = "ref";
  43. public static final String IDREF_ELEMENT = "idref";
  44. public static final String BEAN_REF_ATTRIBUTE = "bean";
  45. public static final String PARENT_REF_ATTRIBUTE = "parent";
  46. public static final String VALUE_ELEMENT = "value";
  47. public static final String NULL_ELEMENT = "null";
  48. public static final String ARRAY_ELEMENT = "array";
  49. public static final String LIST_ELEMENT = "list";
  50. public static final String SET_ELEMENT = "set";
  51. public static final String MAP_ELEMENT = "map";
  52. public static final String ENTRY_ELEMENT = "entry";
  53. public static final String KEY_ELEMENT = "key";
  54. public static final String KEY_ATTRIBUTE = "key";
  55. public static final String KEY_REF_ATTRIBUTE = "key-ref";
  56. public static final String VALUE_REF_ATTRIBUTE = "value-ref";
  57. public static final String PROPS_ELEMENT = "props";
  58. public static final String PROP_ELEMENT = "prop";
  59. public static final String MERGE_ATTRIBUTE = "merge";
  60. public static final String QUALIFIER_ELEMENT = "qualifier";
  61. public static final String QUALIFIER_ATTRIBUTE_ELEMENT = "attribute";
  62. public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";
  63. public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge";
  64. public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";
  65. public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates";
  66. public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method";
  67. public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method";
  68. private static final String SINGLETON_ATTRIBUTE = "singleton";

populateDefaults

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#populateDefaults方法解析属性赋值给DocumentDefaultsDefinition对象

  • 代码逻辑如下

    1. 读取属性
    2. 判断是否默认值
    3. 判断是否存在属性
    4. 赋值
  1. protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) {
  2. // 获取 default-lazy-init 属性值
  3. String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
  4. // 判断是否是默认值
  5. if (isDefaultValue(lazyInit)) {
  6. // Potentially inherited from outer <beans> sections, otherwise falling back to false.
  7. lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
  8. }
  9. defaults.setLazyInit(lazyInit);
  10. String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
  11. if (isDefaultValue(merge)) {
  12. // Potentially inherited from outer <beans> sections, otherwise falling back to false.
  13. merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
  14. }
  15. defaults.setMerge(merge);
  16. String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
  17. if (isDefaultValue(autowire)) {
  18. // Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
  19. autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
  20. }
  21. defaults.setAutowire(autowire);
  22. if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
  23. defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
  24. }
  25. else if (parentDefaults != null) {
  26. defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
  27. }
  28. if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
  29. defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
  30. }
  31. else if (parentDefaults != null) {
  32. defaults.setInitMethod(parentDefaults.getInitMethod());
  33. }
  34. if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
  35. defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
  36. }
  37. else if (parentDefaults != null) {
  38. defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
  39. }
  40. defaults.setSource(this.readerContext.extractSource(root));
  41. }

DocumentDefaultsDefinition

  • 全路径:org.springframework.beans.factory.xml.DocumentDefaultsDefinition
  • 下面放出类的属性标记
  1. public class DocumentDefaultsDefinition implements DefaultsDefinition {
  2. /**
  3. * true or false
  4. */
  5. @Nullable
  6. private String lazyInit;
  7. /**
  8. * true or false
  9. */
  10. @Nullable
  11. private String merge;
  12. /**
  13. * no or byName or byType
  14. */
  15. @Nullable
  16. private String autowire;
  17. /**
  18. * default-autowire-candidates 属性值
  19. */
  20. @Nullable
  21. private String autowireCandidates;
  22. /**
  23. * 实例化方法
  24. */
  25. @Nullable
  26. private String initMethod;
  27. /**
  28. * 摧毁方法
  29. */
  30. @Nullable
  31. private String destroyMethod;
  32. @Nullable
  33. private Object source;
  34. }

checkNameUniqueness

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#checkNameUniqueness

  • 判断 beanName 是否被使用, bean 别名是否被使用

  1. /**
  2. * Validate that the specified bean name and aliases have not been used already
  3. * within the current level of beans element nesting.
  4. *
  5. * 判断 beanName 是否被使用, bean 别名是否被使用
  6. */
  7. protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
  8. // 当前寻找的name
  9. String foundName = null;
  10. // 是否有 beanName
  11. // 使用过的name中是否存在
  12. if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
  13. foundName = beanName;
  14. }
  15. if (foundName == null) {
  16. // 寻找匹配的第一个
  17. foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases);
  18. }
  19. // 抛出异常
  20. if (foundName != null) {
  21. error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);
  22. }
  23. // 加入使用队列
  24. this.usedNames.add(beanName);
  25. this.usedNames.addAll(aliases);
  26. }

createBeanDefinition

  • org.springframework.beans.factory.support.BeanDefinitionReaderUtils#createBeanDefinition
  • 创建具有基本信息的BeanDefinition
    1. parent bean name
    2. bean clsss
    3. bean class name
  1. public static AbstractBeanDefinition createBeanDefinition(
  2. @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
  3. GenericBeanDefinition bd = new GenericBeanDefinition();
  4. // 设置 父bean
  5. bd.setParentName(parentName);
  6. if (className != null) {
  7. if (classLoader != null) {
  8. // 设置 class
  9. // 内部是通过反射创建 class
  10. bd.setBeanClass(ClassUtils.forName(className, classLoader));
  11. }
  12. else {
  13. // 设置 class name
  14. bd.setBeanClassName(className);
  15. }
  16. }
  17. return bd;
  18. }

parseBeanDefinitionElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
  • 该方法用来解析 <bean/> 标签信息

#

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)
  1. @Nullable
  2. public AbstractBeanDefinition parseBeanDefinitionElement(
  3. Element ele, String beanName, @Nullable BeanDefinition containingBean) {
  4. this.parseState.push(new BeanEntry(beanName));
  5. String className = null;
  6. // 是否包含属性 class
  7. if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
  8. className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
  9. }
  10. String parent = null;
  11. // 是否包含属性 parent
  12. if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
  13. parent = ele.getAttribute(PARENT_ATTRIBUTE);
  14. }
  15. try {
  16. // 创建 bean definition
  17. AbstractBeanDefinition bd = createBeanDefinition(className, parent);
  18. // bean definition 属性设置
  19. parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
  20. bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
  21. // 元信息设置
  22. parseMetaElements(ele, bd);
  23. // lookup-override 标签解析
  24. parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
  25. // replaced-method sub-elements 标签解析
  26. parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
  27. // constructor arg 标签解析
  28. parseConstructorArgElements(ele, bd);
  29. // property 标签解析
  30. parsePropertyElements(ele, bd);
  31. // qualifier 标签解析
  32. parseQualifierElements(ele, bd);
  33. // 资源设置
  34. bd.setResource(this.readerContext.getResource());
  35. // source 设置
  36. bd.setSource(extractSource(ele));
  37. return bd;
  38. }
  39. catch (ClassNotFoundException ex) {
  40. error("Bean class [" + className + "] not found", ele, ex);
  41. }
  42. catch (NoClassDefFoundError err) {
  43. error("Class that bean class [" + className + "] depends on not found", ele, err);
  44. }
  45. catch (Throwable ex) {
  46. error("Unexpected failure during bean definition parsing", ele, ex);
  47. }
  48. finally {
  49. this.parseState.pop();
  50. }
  51. return null;
  52. }

parseBeanDefinitionAttributes

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionAttributes

  • 将 xml 标签的数据读取到内存中设置给AbstractBeanDefinition

  1. public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
  2. @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
  3. // 是否存在 singleton 属性
  4. if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
  5. error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
  6. }
  7. // 是否存在 scope 属性
  8. else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
  9. // 设置 scope 属性
  10. bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
  11. }
  12. // bean 定义是否为空
  13. else if (containingBean != null) {
  14. // Take default from containing bean in case of an inner bean definition.
  15. // 设置 bean definition 中的 scope
  16. bd.setScope(containingBean.getScope());
  17. }
  18. // 是否存在 abstract 属性
  19. if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
  20. // 设置 abstract 属性
  21. bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
  22. }
  23. // 获取 lazy-init 属性
  24. String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
  25. // 是否是默认的 lazy-init 属性
  26. if (isDefaultValue(lazyInit)) {
  27. // 获取默认值
  28. lazyInit = this.defaults.getLazyInit();
  29. }
  30. // 设置 lazy-init 属性
  31. bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
  32. // 获取注入方式
  33. String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
  34. // 设置注入方式
  35. bd.setAutowireMode(getAutowireMode(autowire));
  36. // 依赖的bean
  37. if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
  38. String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
  39. bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
  40. }
  41. // autowire-candidate 是否自动注入判断
  42. String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
  43. if (isDefaultValue(autowireCandidate)) {
  44. String candidatePattern = this.defaults.getAutowireCandidates();
  45. if (candidatePattern != null) {
  46. String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
  47. // * 匹配 设置数据
  48. bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
  49. }
  50. }
  51. else {
  52. bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
  53. }
  54. // 获取 primary 书信
  55. if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
  56. bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
  57. }
  58. // 获取 init-method 属性
  59. if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
  60. String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
  61. bd.setInitMethodName(initMethodName);
  62. }
  63. // 没有 init-method 的情况处理
  64. else if (this.defaults.getInitMethod() != null) {
  65. bd.setInitMethodName(this.defaults.getInitMethod());
  66. bd.setEnforceInitMethod(false);
  67. }
  68. // 获取 destroy-method 属性
  69. if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
  70. String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
  71. bd.setDestroyMethodName(destroyMethodName);
  72. }
  73. // 没有 destroy-method 的情况处理
  74. else if (this.defaults.getDestroyMethod() != null) {
  75. bd.setDestroyMethodName(this.defaults.getDestroyMethod());
  76. bd.setEnforceDestroyMethod(false);
  77. }
  78. // 获取 factory-method 属性
  79. if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
  80. bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
  81. }
  82. // 获取 factory-bean 属性
  83. if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
  84. bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
  85. }
  86. return bd;
  87. }

parseMetaElements

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseMetaElements

  • 设置元数据.

    标签meta的解析

  1. public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
  2. // 获取下级标签
  3. NodeList nl = ele.getChildNodes();
  4. // 循环子标签
  5. for (int i = 0; i < nl.getLength(); i++) {
  6. Node node = nl.item(i);
  7. // 设置数据
  8. if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
  9. Element metaElement = (Element) node;
  10. // 获取 key 属性
  11. String key = metaElement.getAttribute(KEY_ATTRIBUTE);
  12. // 获取 value 属性
  13. String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
  14. // 元数据对象设置
  15. BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
  16. // 设置 source
  17. attribute.setSource(extractSource(metaElement));
  18. // 信息添加
  19. attributeAccessor.addMetadataAttribute(attribute);
  20. }
  21. }
  22. }

使用案例

  1. <bean id="apple" class="org.source.hot.spring.overview.ioc.bean.lookup.Apple">
  2. <meta key="meta-key" value="meta-value"/>
  3. </bean>
  1. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/beans/spring-lookup-method.xml");
  2. ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  3. BeanDefinition apple = beanFactory.getBeanDefinition("apple");
  4. Object attribute = apple.getAttribute("meta-key");
  5. System.out.println(attribute);

parseLookupOverrideSubElements

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseLookupOverrideSubElements

  • 解析标签

    lookup-method

  1. public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
  2. // 获取子标签
  3. NodeList nl = beanEle.getChildNodes();
  4. for (int i = 0; i < nl.getLength(); i++) {
  5. Node node = nl.item(i);
  6. // 是否有 lookup-method 属性
  7. if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
  8. Element ele = (Element) node;
  9. // 获取 name 属性
  10. String methodName = ele.getAttribute(NAME_ATTRIBUTE);
  11. // 获取 bean 属性
  12. String beanRef = ele.getAttribute(BEAN_ELEMENT);
  13. // 创建 覆盖依赖
  14. LookupOverride override = new LookupOverride(methodName, beanRef);
  15. // 设置 source
  16. override.setSource(extractSource(ele));
  17. overrides.addOverride(override);
  18. }
  19. }
  20. }

使用案例

  1. <bean id="apple" class="org.source.hot.spring.overview.ioc.bean.lookup.Apple">
  2. <meta key="meta-key" value="meta-value"/>
  3. </bean>
  4. <bean id="shop" class="org.source.hot.spring.overview.ioc.bean.lookup.Shop">
  5. <lookup-method name="getFruits" bean="apple"/>
  6. </bean>
  1. public class LookupMain {
  2. public static void main(String[] args) {
  3. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/beans/spring-lookup-method.xml");
  4. Shop shop = context.getBean("shop", Shop.class);
  5. System.out.println(shop.getFruits().getName());
  6. }
  7. }

parseReplacedMethodSubElements

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseReplacedMethodSubElements

  • 解析标签

    replaced-method

  1. public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
  2. // 子节点获取
  3. NodeList nl = beanEle.getChildNodes();
  4. for (int i = 0; i < nl.getLength(); i++) {
  5. Node node = nl.item(i);
  6. // 是否包含 replaced-method 属性
  7. if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
  8. Element replacedMethodEle = (Element) node;
  9. // 获取 name 属性
  10. String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
  11. // 获取 replacer
  12. String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
  13. // 对象组装
  14. ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
  15. // Look for arg-type match elements.
  16. // 子节点属性
  17. // 处理 arg-type 标签
  18. List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
  19. for (Element argTypeEle : argTypeEles) {
  20. // 获取 match 数据值
  21. String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
  22. // match 信息设置
  23. match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
  24. if (StringUtils.hasText(match)) {
  25. // 添加类型标识
  26. replaceOverride.addTypeIdentifier(match);
  27. }
  28. }
  29. // 设置 source
  30. replaceOverride.setSource(extractSource(replacedMethodEle));
  31. // 重载列表添加
  32. overrides.addOverride(replaceOverride);
  33. }
  34. }
  35. }
  • 使用案例
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="apple" class="org.source.hot.spring.overview.ioc.bean.lookup.Apple">
  6. <replaced-method replacer="methodReplacerApple" name="hello" >
  7. <arg-type>String</arg-type>
  8. </replaced-method>
  9. </bean>
  10. <bean id="methodReplacerApple" class="org.source.hot.spring.overview.ioc.bean.lookup.MethodReplacerApple">
  11. </bean>
  12. </beans>
  1. public class MethodReplacerApple implements MethodReplacer {
  2. @Override
  3. public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
  4. System.out.println("方法替换");
  5. return obj;
  6. }
  7. }

replacer 需要使用 MethodReplacer 实现类

parseConstructorArgElements

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseConstructorArgElements

  • 解析constructor-arg标签

  1. public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
  2. // 获取
  3. NodeList nl = beanEle.getChildNodes();
  4. for (int i = 0; i < nl.getLength(); i++) {
  5. Node node = nl.item(i);
  6. if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
  7. // 解析 constructor-arg 下级标签
  8. parseConstructorArgElement((Element) node, bd);
  9. }
  10. }
  11. }
  1. public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
  2. // 获取 index 属性
  3. String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
  4. // 获取 type 属性
  5. String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
  6. // 获取 name 属性
  7. String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
  8. if (StringUtils.hasLength(indexAttr)) {
  9. try {
  10. // 构造参数的所以未知
  11. int index = Integer.parseInt(indexAttr);
  12. if (index < 0) {
  13. error("'index' cannot be lower than 0", ele);
  14. }
  15. else {
  16. try {
  17. this.parseState.push(new ConstructorArgumentEntry(index));
  18. // 解析 property 标签
  19. Object value = parsePropertyValue(ele, bd, null);
  20. // 创建 构造函数的 属性控制类
  21. ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
  22. if (StringUtils.hasLength(typeAttr)) {
  23. // 类型设置
  24. valueHolder.setType(typeAttr);
  25. }
  26. if (StringUtils.hasLength(nameAttr)) {
  27. // 名称设置
  28. valueHolder.setName(nameAttr);
  29. }
  30. // 源设置
  31. valueHolder.setSource(extractSource(ele));
  32. if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
  33. error("Ambiguous constructor-arg entries for index " + index, ele);
  34. }
  35. else {
  36. // 添加 构造函数信息
  37. bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
  38. }
  39. }
  40. finally {
  41. this.parseState.pop();
  42. }
  43. }
  44. }
  45. catch (NumberFormatException ex) {
  46. error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
  47. }
  48. }
  49. else {
  50. try {
  51. this.parseState.push(new ConstructorArgumentEntry());
  52. // 解析 property 标签
  53. Object value = parsePropertyValue(ele, bd, null);
  54. // 创建 构造函数的 属性控制类
  55. ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
  56. if (StringUtils.hasLength(typeAttr)) {
  57. // 类型设置
  58. valueHolder.setType(typeAttr);
  59. }
  60. if (StringUtils.hasLength(nameAttr)) {
  61. // 名称设置
  62. valueHolder.setName(nameAttr);
  63. }
  64. // 源设置
  65. valueHolder.setSource(extractSource(ele));
  66. // 添加 构造函数信息
  67. bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
  68. }
  69. finally {
  70. this.parseState.pop();
  71. }
  72. }
  73. }

parseConstructorArgElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseConstructorArgElement

  • 解析 constructor-arg 下级标签

  1. @Nullable
  2. public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
  3. String elementName = (propertyName != null ?
  4. "<property> element for property '" + propertyName + "'" :
  5. "<constructor-arg> element");
  6. // Should only have one child element: ref, value, list, etc.
  7. NodeList nl = ele.getChildNodes();
  8. Element subElement = null;
  9. for (int i = 0; i < nl.getLength(); i++) {
  10. Node node = nl.item(i);
  11. if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
  12. !nodeNameEquals(node, META_ELEMENT)) {
  13. // Child element is what we're looking for.
  14. if (subElement != null) {
  15. error(elementName + " must not contain more than one sub-element", ele);
  16. }
  17. else {
  18. subElement = (Element) node;
  19. }
  20. }
  21. }
  22. // ref 属性是否存在
  23. boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
  24. // value 属性是否存在
  25. boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
  26. if ((hasRefAttribute && hasValueAttribute) ||
  27. ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
  28. error(elementName +
  29. " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
  30. }
  31. if (hasRefAttribute) {
  32. // 获取 ref 属性值
  33. String refName = ele.getAttribute(REF_ATTRIBUTE);
  34. if (!StringUtils.hasText(refName)) {
  35. error(elementName + " contains empty 'ref' attribute", ele);
  36. }
  37. // 创建 连接对象
  38. RuntimeBeanReference ref = new RuntimeBeanReference(refName);
  39. ref.setSource(extractSource(ele));
  40. return ref;
  41. }
  42. else if (hasValueAttribute) {
  43. // 获取 value
  44. TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
  45. valueHolder.setSource(extractSource(ele));
  46. return valueHolder;
  47. }
  48. else if (subElement != null) {
  49. return parsePropertySubElement(subElement, bd);
  50. }
  51. else {
  52. // Neither child element nor "ref" or "value" attribute found.
  53. error(elementName + " must specify a ref or value", ele);
  54. return null;
  55. }
  56. }

parsePropertySubElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parsePropertySubElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
  1. @Nullable
  2. public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
  3. // 解析 property 下级标签
  4. return parsePropertySubElement(ele, bd, null);
  5. }

parsePropertySubElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parsePropertySubElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition, java.lang.String)
  1. @Nullable
  2. public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
  3. if (!isDefaultNamespace(ele)) {
  4. // 嵌套分析
  5. return parseNestedCustomElement(ele, bd);
  6. }
  7. else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
  8. // 解析 bean 标签
  9. BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
  10. if (nestedBd != null) {
  11. // 装饰 bean define
  12. nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
  13. }
  14. return nestedBd;
  15. }
  16. // ref 名称判断
  17. else if (nodeNameEquals(ele, REF_ELEMENT)) {
  18. // A generic reference to any name of any bean.
  19. // 获取 ref 属性
  20. String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
  21. boolean toParent = false;
  22. if (!StringUtils.hasLength(refName)) {
  23. // A reference to the id of another bean in a parent context.
  24. // 获取 parent 属性
  25. refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
  26. toParent = true;
  27. if (!StringUtils.hasLength(refName)) {
  28. error("'bean' or 'parent' is required for <ref> element", ele);
  29. return null;
  30. }
  31. }
  32. if (!StringUtils.hasText(refName)) {
  33. error("<ref> element contains empty target attribute", ele);
  34. return null;
  35. }
  36. // bean 连接对象创建
  37. RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
  38. ref.setSource(extractSource(ele));
  39. return ref;
  40. }
  41. else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
  42. return parseIdRefElement(ele);
  43. }
  44. else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
  45. return parseValueElement(ele, defaultValueType);
  46. }
  47. else if (nodeNameEquals(ele, NULL_ELEMENT)) {
  48. // It's a distinguished null value. Let's wrap it in a TypedStringValue
  49. // object in order to preserve the source location.
  50. TypedStringValue nullHolder = new TypedStringValue(null);
  51. nullHolder.setSource(extractSource(ele));
  52. return nullHolder;
  53. }
  54. else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
  55. return parseArrayElement(ele, bd);
  56. }
  57. else if (nodeNameEquals(ele, LIST_ELEMENT)) {
  58. return parseListElement(ele, bd);
  59. }
  60. else if (nodeNameEquals(ele, SET_ELEMENT)) {
  61. return parseSetElement(ele, bd);
  62. }
  63. else if (nodeNameEquals(ele, MAP_ELEMENT)) {
  64. return parseMapElement(ele, bd);
  65. }
  66. else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
  67. return parsePropsElement(ele);
  68. }
  69. else {
  70. error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
  71. return null;
  72. }
  73. }

parseIdRefElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseIdRefElement
  1. @Nullable
  2. public Object parseIdRefElement(Element ele) {
  3. // A generic reference to any name of any bean.
  4. // 获取 bean 属性
  5. String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
  6. if (!StringUtils.hasLength(refName)) {
  7. error("'bean' is required for <idref> element", ele);
  8. return null;
  9. }
  10. if (!StringUtils.hasText(refName)) {
  11. error("<idref> element contains empty target attribute", ele);
  12. return null;
  13. }
  14. // 设置 bean 链接对象
  15. RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName);
  16. // 设置原
  17. ref.setSource(extractSource(ele));
  18. return ref;
  19. }

parseValueElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseValueElement
  1. public Object parseValueElement(Element ele, @Nullable String defaultTypeName) {
  2. // It's a literal value.
  3. // 获取 xml 中的文本变量
  4. String value = DomUtils.getTextValue(ele);
  5. // 获取 type 属性
  6. String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
  7. // 类型
  8. String typeName = specifiedTypeName;
  9. if (!StringUtils.hasText(typeName)) {
  10. typeName = defaultTypeName;
  11. }
  12. try {
  13. // 创建类型值
  14. TypedStringValue typedValue = buildTypedStringValue(value, typeName);
  15. typedValue.setSource(extractSource(ele));
  16. typedValue.setSpecifiedTypeName(specifiedTypeName);
  17. return typedValue;
  18. }
  19. catch (ClassNotFoundException ex) {
  20. error("Type class [" + typeName + "] not found for <value> element", ele, ex);
  21. return value;
  22. }
  23. }
buildTypedStringValue
  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#buildTypedStringValue
  • 构造对象, 没有创建对象
  1. protected TypedStringValue buildTypedStringValue(String value, @Nullable String targetTypeName)
  2. throws ClassNotFoundException {
  3. // class loader
  4. ClassLoader classLoader = this.readerContext.getBeanClassLoader();
  5. TypedStringValue typedValue;
  6. if (!StringUtils.hasText(targetTypeName)) {
  7. typedValue = new TypedStringValue(value);
  8. }
  9. else if (classLoader != null) {
  10. // 目标类
  11. Class<?> targetType = ClassUtils.forName(targetTypeName, classLoader);
  12. // 构造
  13. typedValue = new TypedStringValue(value, targetType);
  14. }
  15. else {
  16. // 构造
  17. typedValue = new TypedStringValue(value, targetTypeName);
  18. }
  19. return typedValue;
  20. }

parseArrayElement

  1. public Object parseArrayElement(Element arrayEle, @Nullable BeanDefinition bd) {
  2. // 获取 value-type 属性
  3. String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
  4. // 子节点
  5. NodeList nl = arrayEle.getChildNodes();
  6. // 合并 array 的类
  7. ManagedArray target = new ManagedArray(elementType, nl.getLength());
  8. target.setSource(extractSource(arrayEle));
  9. target.setElementTypeName(elementType);
  10. target.setMergeEnabled(parseMergeAttribute(arrayEle));
  11. // 处理 collection 节点
  12. parseCollectionElements(nl, target, bd, elementType);
  13. return target;
  14. }

parseListElement

  1. public List<Object> parseListElement(Element collectionEle, @Nullable BeanDefinition bd) {
  2. String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
  3. NodeList nl = collectionEle.getChildNodes();
  4. ManagedList<Object> target = new ManagedList<>(nl.getLength());
  5. target.setSource(extractSource(collectionEle));
  6. target.setElementTypeName(defaultElementType);
  7. target.setMergeEnabled(parseMergeAttribute(collectionEle));
  8. parseCollectionElements(nl, target, bd, defaultElementType);
  9. return target;
  10. }

parseSetElement

  1. public Set<Object> parseSetElement(Element collectionEle, @Nullable BeanDefinition bd) {
  2. String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
  3. NodeList nl = collectionEle.getChildNodes();
  4. ManagedSet<Object> target = new ManagedSet<>(nl.getLength());
  5. target.setSource(extractSource(collectionEle));
  6. target.setElementTypeName(defaultElementType);
  7. target.setMergeEnabled(parseMergeAttribute(collectionEle));
  8. parseCollectionElements(nl, target, bd, defaultElementType);
  9. return target;
  10. }
parseCollectionElements
  • parseArrayElementparseListElementparseSetElement 都围绕者下面这个方法进行数据合并
  1. protected void parseCollectionElements(
  2. NodeList elementNodes, Collection<Object> target, @Nullable BeanDefinition bd, String defaultElementType) {
  3. for (int i = 0; i < elementNodes.getLength(); i++) {
  4. Node node = elementNodes.item(i);
  5. if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
  6. // 处理子节点
  7. target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
  8. }
  9. }
  10. }

parseMapElement

  1. public Map<Object, Object> parseMapElement(Element mapEle, @Nullable BeanDefinition bd) {
  2. // key-type 属性获取
  3. String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);
  4. // value-type 属性互殴去
  5. String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
  6. // entry 标签获取
  7. List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);
  8. // 合并 map 对象
  9. ManagedMap<Object, Object> map = new ManagedMap<>(entryEles.size());
  10. map.setSource(extractSource(mapEle));
  11. map.setKeyTypeName(defaultKeyType);
  12. map.setValueTypeName(defaultValueType);
  13. map.setMergeEnabled(parseMergeAttribute(mapEle));
  14. // 循环 entry 节点
  15. for (Element entryEle : entryEles) {
  16. // Should only have one value child element: ref, value, list, etc.
  17. // Optionally, there might be a key child element.
  18. NodeList entrySubNodes = entryEle.getChildNodes();
  19. Element keyEle = null;
  20. Element valueEle = null;
  21. for (int j = 0; j < entrySubNodes.getLength(); j++) {
  22. Node node = entrySubNodes.item(j);
  23. if (node instanceof Element) {
  24. Element candidateEle = (Element) node;
  25. // 节点名称是否为 key
  26. if (nodeNameEquals(candidateEle, KEY_ELEMENT)) {
  27. if (keyEle != null) {
  28. error("<entry> element is only allowed to contain one <key> sub-element", entryEle);
  29. }
  30. else {
  31. keyEle = candidateEle;
  32. }
  33. }
  34. else {
  35. // Child element is what we're looking for.
  36. if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) {
  37. // the element is a <description> -> ignore it
  38. }
  39. else if (valueEle != null) {
  40. error("<entry> element must not contain more than one value sub-element", entryEle);
  41. }
  42. else {
  43. valueEle = candidateEle;
  44. }
  45. }
  46. }
  47. }
  48. // Extract key from attribute or sub-element.
  49. Object key = null;
  50. // key 属性
  51. boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE);
  52. // key-ref 属性
  53. boolean hasKeyRefAttribute = entryEle.hasAttribute(KEY_REF_ATTRIBUTE);
  54. if ((hasKeyAttribute && hasKeyRefAttribute) ||
  55. (hasKeyAttribute || hasKeyRefAttribute) && keyEle != null) {
  56. error("<entry> element is only allowed to contain either " +
  57. "a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle);
  58. }
  59. if (hasKeyAttribute) {
  60. // TypedStringValue 构建
  61. key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle);
  62. }
  63. else if (hasKeyRefAttribute) {
  64. // key-ref 属性获取
  65. String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE);
  66. if (!StringUtils.hasText(refName)) {
  67. error("<entry> element contains empty 'key-ref' attribute", entryEle);
  68. }
  69. // 创建 bean 连接对象
  70. RuntimeBeanReference ref = new RuntimeBeanReference(refName);
  71. ref.setSource(extractSource(entryEle));
  72. key = ref;
  73. }
  74. else if (keyEle != null) {
  75. // 获取 key 数据
  76. key = parseKeyElement(keyEle, bd, defaultKeyType);
  77. }
  78. else {
  79. error("<entry> element must specify a key", entryEle);
  80. }
  81. // Extract value from attribute or sub-element.
  82. Object value = null;
  83. // value 属性是否存在
  84. boolean hasValueAttribute = entryEle.hasAttribute(VALUE_ATTRIBUTE);
  85. // value-ref 属性是否存在
  86. boolean hasValueRefAttribute = entryEle.hasAttribute(VALUE_REF_ATTRIBUTE);
  87. // 是否存在 value-type 属性
  88. boolean hasValueTypeAttribute = entryEle.hasAttribute(VALUE_TYPE_ATTRIBUTE);
  89. if ((hasValueAttribute && hasValueRefAttribute) ||
  90. (hasValueAttribute || hasValueRefAttribute) && valueEle != null) {
  91. error("<entry> element is only allowed to contain either " +
  92. "'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
  93. }
  94. if ((hasValueTypeAttribute && hasValueRefAttribute) ||
  95. (hasValueTypeAttribute && !hasValueAttribute) ||
  96. (hasValueTypeAttribute && valueEle != null)) {
  97. error("<entry> element is only allowed to contain a 'value-type' " +
  98. "attribute when it has a 'value' attribute", entryEle);
  99. }
  100. if (hasValueAttribute) {
  101. // 获取 value-type 属性
  102. String valueType = entryEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
  103. if (!StringUtils.hasText(valueType)) {
  104. // 设置默认value-type
  105. valueType = defaultValueType;
  106. }
  107. // 创建 TypedStringValue
  108. value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), valueType, entryEle);
  109. }
  110. else if (hasValueRefAttribute) {
  111. // 获取 value-ref 属性
  112. String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE);
  113. if (!StringUtils.hasText(refName)) {
  114. error("<entry> element contains empty 'value-ref' attribute", entryEle);
  115. }
  116. // 创建 bean 链接对象
  117. RuntimeBeanReference ref = new RuntimeBeanReference(refName);
  118. ref.setSource(extractSource(entryEle));
  119. value = ref;
  120. }
  121. else if (valueEle != null) {
  122. value = parsePropertySubElement(valueEle, bd, defaultValueType);
  123. }
  124. else {
  125. error("<entry> element must specify a value", entryEle);
  126. }
  127. // Add final key and value to the Map.
  128. map.put(key, value);
  129. }
  130. return map;
  131. }

parsePropsElement

parsePropertyElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parsePropertyElement
  1. public void parsePropertyElement(Element ele, BeanDefinition bd) {
  2. String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
  3. if (!StringUtils.hasLength(propertyName)) {
  4. error("Tag 'property' must have a 'name' attribute", ele);
  5. return;
  6. }
  7. this.parseState.push(new PropertyEntry(propertyName));
  8. try {
  9. if (bd.getPropertyValues().contains(propertyName)) {
  10. error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
  11. return;
  12. }
  13. // 解析 property 标签
  14. Object val = parsePropertyValue(ele, bd, propertyName);
  15. // 构造 PropertyValue 对象
  16. PropertyValue pv = new PropertyValue(propertyName, val);
  17. // 解析元信息
  18. parseMetaElements(ele, pv);
  19. pv.setSource(extractSource(ele));
  20. // 添加 pv 结构
  21. bd.getPropertyValues().addPropertyValue(pv);
  22. }
  23. finally {
  24. this.parseState.pop();
  25. }
  26. }

parseQualifierElements

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseQualifierElements
  • 解析 qualifier 标签和下级标签
  1. public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
  2. NodeList nl = beanEle.getChildNodes();
  3. for (int i = 0; i < nl.getLength(); i++) {
  4. Node node = nl.item(i);
  5. if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
  6. // 单个解析
  7. parseQualifierElement((Element) node, bd);
  8. }
  9. }
  10. }

parseQualifierElement

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseQualifierElement
  1. public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
  2. // 获取 type 属性
  3. String typeName = ele.getAttribute(TYPE_ATTRIBUTE);
  4. if (!StringUtils.hasLength(typeName)) {
  5. error("Tag 'qualifier' must have a 'type' attribute", ele);
  6. return;
  7. }
  8. this.parseState.push(new QualifierEntry(typeName));
  9. try {
  10. // 自动注入对象创建
  11. AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
  12. // 设置源
  13. qualifier.setSource(extractSource(ele));
  14. // 获取 value 属性
  15. String value = ele.getAttribute(VALUE_ATTRIBUTE);
  16. if (StringUtils.hasLength(value)) {
  17. // 设置 属性 value , value
  18. qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
  19. }
  20. NodeList nl = ele.getChildNodes();
  21. for (int i = 0; i < nl.getLength(); i++) {
  22. Node node = nl.item(i);
  23. if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
  24. Element attributeEle = (Element) node;
  25. // 获取 key 属性
  26. String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
  27. // 获取 value 属性
  28. String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
  29. if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
  30. // key value 属性映射
  31. BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
  32. attribute.setSource(extractSource(attributeEle));
  33. // 添加 qualifier 属性值
  34. qualifier.addMetadataAttribute(attribute);
  35. }
  36. else {
  37. error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
  38. return;
  39. }
  40. }
  41. }
  42. // 添加 qualifier
  43. bd.addQualifier(qualifier);
  44. }
  45. finally {
  46. this.parseState.pop();
  47. }
  48. }