Spring读源码系列02----默认标签解析过程
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列02----默认标签解析过程相关的知识,希望对你有一定的参考价值。
Spring读源码系列02----默认标签解析过程
- Bean标签的解析及注册
- DefaultBeanDefinitionDocumentReader#processBeanDefinition----对Bean标签进行处理的方法
- BeanDefinitionParserDelegate#parseBeanDefinitionElement从xml配置信息--->BeanDefinition
- BeanDefinitionParserDelegate#parseBeanDefinitionElement---将bean标签映射到BeanDefinition
- BeanDefinitionParserDelegate#createBeanDefinition创建用于属性承载的BeanDefinition
- BeanDefinitionParserDelegate#parseBeanDefinitionAttributes---解析bean标签上能标注的各种属性
- BeanDefinitionParserDelegate#parseMetaElements---解析元数据
- BeanDefinitionParserDelegate#parseLookupOverrideSubElements---解析子元素lookup-method
- BeanDefinitionParserDelegate#parseReplacedMethodSubElements---解析子元素replace-method
- BeanDefinitionParserDelegate#parseConstructorArgElements----解析子元素constructor-arg
- BeanDefinitionParserDelegate#parsePropertyElements----解析子元素property
- BeanDefinitionParserDelegate#parseQualifierElements----解析子元素qualifier
- AbstractBeanDefinition属性
- 解析默认标签中的自定义标签
- 注册解析的BeanDefinition
- 通知监听器解析及注册完成
- Alias标签的解析
- import标签的解析
- 嵌入式Bean标签的解析
阅读本系列之前,建议先从本专栏的两个不同视角学习spring的系列作为入门学习点(这两个系列会持续更新),先大体理解spring的架构设计与精髓,然后再来阅读本系列,深入源码分析,而不再纸上谈兵。
从整体来学spring系列文章:
Spring复杂的BeanFactory继承体系该如何理解? ----上
Spring复杂的BeanFactory继承体系该如何理解? ----中
Spring复杂的BeanFactory继承体系该如何理解?—中下
Spring复杂的BeanFactory继承体系该如何理解?—下
该系列持续更新中…
独特视角学习spring系列文章:
该系列持续更新中…
本系列文章:
之前的流程建议大家看一下01篇
这里一句话简单概括一下01篇的流程: 定位xml文件资源,包装为Resource对象—>xml文件被解析为一颗DOM树,即Document对象—>BeanDefinitionDocumentReader负责对Document对象进行解析—>BeanDefinitionDocumentReader内部又把解析Document对象的事情委托给了BeanDefinitionParserDelegate来完成
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
//对imprt标签进行处理
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT))
importBeanDefinitionResource(ele);
//对alias标签进行处理
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT))
processAliasRegistration(ele);
//对bean标签进行处理
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT))
processBeanDefinition(ele, delegate);
//对beans标签进行处理
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT))
doRegisterBeanDefinitions(ele);
Bean标签的解析及注册
DefaultBeanDefinitionDocumentReader#processBeanDefinition----对Bean标签进行处理的方法
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
//委托BeanDefinitionParserDelegate来对bean标签进行解析
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null)
//对自定义子标签再进行处理---如果存在的话
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try
// Register the final decorated instance.
//注册BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
catch (BeanDefinitionStoreException ex)
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
// Send registration event.
//释放事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
BeanDefinitionParserDelegate#parseBeanDefinitionElement从xml配置信息—>BeanDefinition
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele)
//这里的ele是bean标签
return parseBeanDefinitionElement(ele, null);
目标方法:
/**
* Parses the supplied <bean> element. May return null
* if there were errors during parse. Errors are reported to the
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)
//解析id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//解析name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//存放bean的别名的集合
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr))
//分割name属性---得到的是别名数组
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
//加入别名集合
aliases.addAll(Arrays.asList(nameArr));
//id规定了beanName
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty())
//beanName为空,就把别名数组中第一个元素拿出来作为beanName
beanName = aliases.remove(0);
if (logger.isTraceEnabled())
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
if (containingBean == null)
//别名不能重复
checkNameUniqueness(beanName, aliases, ele);
/
//传入bean标签,beanName,containingBean开始正式对bean标签进行解析得到beanDefinition
//返回的beanDefinition类型是GenericBeanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
///
if (beanDefinition != null)
//beanName为空---没给id,别名也没有该咋办?
if (!StringUtils.hasText(beanName))
try
//containingBean不为空
if (containingBean != null)
//自动生成一个beanName
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
else
//如果containingBean为空,那就通过下面的方式生成一个beanName
//这里获得的beanName是全类名加上一个#0---->org.deepSpring.Bean#0
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName))
aliases.add(beanClassName);
if (logger.isTraceEnabled())
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
catch (Exception ex)
error(ex.getMessage(), ele);
return null;
//得到别名数组
String[] aliasesArray = StringUtils.toStringArray(aliases);
//生成BeanDefinitionHolder----这个类干的事情就是整合了beanDefinition,beanName和aliasesArray
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
return null;
BeanDefinitionParserDelegate#parseBeanDefinitionElement—将bean标签映射到BeanDefinition
记住该类BeanDefinitionParserDelegate才是被委托解析xml生成BeanDefinition的对象
/**
* Parse the bean definition itself, without regard to name or aliases. May return
null if problems occurred during the parsing of the bean definition.
*/
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean)
//跟踪解析的状态
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE))
//获取bean标签里面的className属性
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE))
//获取bean标签里面的parent属性
parent = ele.getAttribute(PARENT_ATTRIBUTE);
try
//生成BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//硬编码解析默认bean的各种属性---因为BeanDefinition里面成员属性和bean标签里面能写的属性一一映射
//这样的话,每解析出一个属性,就直接设置BeanDefinition对应映射到的值即可
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//提取description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析元数据
parseMetaElements(ele, bd);
//解析lookup-method属性
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析replace-method属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造函数参数
parseConstructorArgElements(ele, bd);
//解析property子元素
parsePropertyElements(ele, bd);
//解析qualifier子元素
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
catch (ClassNotFoundException ex)
error("Bean class [" + className + "] not found", ele, ex);
catch (NoClassDefFoundError err)
error("Class that bean class [" + className + "] depends on not found", ele, err);
catch (Throwable ex)
error("Unexpected failure during bean definition parsing", ele, ex);
finally
this.parseState.pop();
return null;
BeanDefinitionParserDelegate#createBeanDefinition创建用于属性承载的BeanDefinition
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
throws ClassNotFoundException
//BeanDefinitionReaderUtils来创建BeanDefinition
//这个工具类还可以用来生成beanName,注册BeanDefinition上面都讲到过了
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
BeanDefinitionReaderUtils类:
public static AbstractBeanDefinition createBeanDefinition(
@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException
//创建的是GenericBeanDefinition
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null)
if (classLoader != null)
bd.setBeanClass(ClassUtils.forName(className, classLoader));
else
bd.setBeanClassName(className);
return bd;
BeanDefinitionParserDelegate#parseBeanDefinitionAttributes—解析bean标签上能标注的各种属性
下面我们开始对bean标签里面的属性进行解析了
/**
* Apply the attributes of the given bean element to the given bean * definition.
* @param ele bean declaration element
* @param beanName bean name
* @param containingBean containing bean definition
* @return a bean definition initialized according to the bean element attributes
*/
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd)
//解析scope属性
if (ele.hasAttribute(SINGLETON_ATTRIBUTE))
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
else if (ele.hasAttribute(SCOPE_ATTRIBUTE))
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
else if (containingBean != null)
//如果是内嵌的beanDefinition情况下,没有单独指定scope属性,则使用父类的默认属性
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
//解析abstract属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE))
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
//解析lazy-init属性
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (isDefaultValue(lazyInit))
lazyInit = this.defaults.getLazyInit();
//如果没有数组,或设置成其他字符都会被设置成false---即默认都不是懒惰初始化的
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
//解析autowire属性
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
//设置自动注入模式--构造器注入,按照类型注入等
bd.setAutowireMode(getAutowireMode(autowire));
//解析depends-on属性
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE))
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
//解析autowire-candidate属性
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if (isDefaultValue(autowireCandidate))
String candidatePattern = this.defaults.getAutowireCandidates();
if (candidatePattern != null)
String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
else
bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
//解析primary属性
if (ele.hasAttribute(PRIMARY_ATTRIBUTE))
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
//解析init-method属性
if Spring读源码系列番外篇---02---PropertyResolver的结构体系剖析---上