上一节中,我们详细分析了spring在解析xml,创建beanFactory的前期准备工作,这一节我们将会详细分析一下spring是如何解析系统默认标签的。
首先进入解析默认标签方法的入口,parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate):
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//import标签的解析
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);
}
//bean标签的解析
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
doRegisterBeanDefinitions(ele);
}
}
这边我们就看看bean标签的解析过程,processBeanDefinition(ele, delegate):
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//解析document对象为一个BeanDefinitionHolder对象
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//将解析出来的BeanDefinitionHolder对象注册到applicationContext上
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//发布一个注册成功的event
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
继续进入解析document对象的代码,delegate.parseBeanDefinitionElement(ele):
public BeanDefinitionHolder (Element ele, @Nullable BeanDefinition containingBean) {
//获取bean标签的id属性和name属性
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//获取bean标签的别名属性
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
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 = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
//校验beanName和aliases之前没有使用过,delegate对象中使用两个set去记录
checkNameUniqueness(beanName, aliases, ele);
}
//解析出beanDefinition对象
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
//如果没有beanName,则根据beanDefiNition生成一个beanName
if (!StringUtils.hasText(beanName)) {
……
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//封装出BeanDefinitionHolder对象并返回
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
进入解析beanDefinition对象的代码,parseBeanDefinitionElement(ele, beanName, containingBean):
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
//设置解析状态
this.parseState.push(new BeanEntry(beanName));
//获取className和parent
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//初始化一个GenericBeanDefinition,
//如果readerContext对象中有classload,那么加载该类并设置beanClass属性
//如果没有classload对象,那么就将className设置为beanClassName属性
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
/**
* 解析bean标签的属性,如果没有配置,则会到default属性中看看有没有
* 1.设置scope属性
* 2.设置abstract属性
* 3.设置lazy-init属性,默认false
* 4.设置autowireMode属性,分别有0-no,1-byName,2-byType,3-constructor,4-autodetect
* 5.设置depend-on属性
* 6.设置autowire-candidate属性
* 7.设置primary属性
* 8.设置init-method属性
* 9.设置destroy-method属性
* 10.设置factory-method属性
* 11.设置factory-bean属性
*/
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//如果有description子标签,则设置其描述信息
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析元数据标签 <meta>标签的key,value
parseMetaElements(ele, bd);
//解析lookup-method标签,为本类中的某个抽象方法设置返回值
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析replaced-method标签,替换本类中的方法的内容
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造函数标签,并将构造函数参数的信息存入constructorArgumentValues
parseConstructorArgElements(ele, bd);
//解析property标签,并将值的信息存入到propertyValues
parsePropertyElements(ele, bd);
//解析qualifier标签,并将要注入的对象信息存入qualifiers属性中
parseQualifierElements(ele, bd);
//设置beanDefinition的Resource和Source
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch ……
finally {
//清除状态
this.parseState.pop();
}
return null;
}
到这里,我们就获取到了BeanDefinitionHolder对象,最后我们在看一下注册的逻辑:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
//注册beanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//如果有别名,则记录别名和beanName的映射
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
进入注册代码,registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()):
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
……校验代码省略
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//已经注册过
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
……日志打印省略
//覆盖原来的注册
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//如果有bean已经创建了,beanDefinitionNames的就不能modify,所以要重新new一个
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
//manualSingletonNames中将beanName移除,manualSingletonNames是用来缓存手动注册的单例bean的
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
//递归清除这个beanName和它的子类的所有缓存
resetBeanDefinition(beanName);
}
}
至此,一个系统标签的解析就已经完成了,下面我们来做一个小结:
- 首先会根据标签的类型进行不同的解析,import是import的解析,bean是bean的,这里是拿bean的解析为例
- 通过解析element对象,生成一个BeanDefinitionHolder对象
2.1 解析beanName
2.2 通过beanName创建一个beanDefinition
2.3 解析标签属性,并将结果存入beanDefinition
2.4 解析子标签内容,并将结果存入beanDefinition
2.5 将beanDefinition包装成BeanDefinitionHolder,并返回 - 将这个BeanDefinitionHolder对象注册到applicationContext