默认标签的解析过程:
DefaultBeanDefinitonDocumentReader class中processBeanDefinition
(1) 该方法先解析element元素获得BeanDefinitionHolder,
(2) 由BeanDefintionParserDelegate对于holder进行装饰加工
(3) 由BeanDefinitionReaderUtils.registerBeanDefinition对于holder进行注册
(4) 之后发送注册事件getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))
其中主要的方法如下:
protected voidprocessBeanDefinition(Elementele,BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolderbdHolder= delegate.parseBeanDefinitionElement(ele);//(1)
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//(2)
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,getReaderContext().getRegistry());//(3)
}
catch(BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name'" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(newBeanComponentDefinition(bdHolder));//(4)
}
}
下面细节介绍首先是
(1) 对于element元素的解析
BeanDefinitionHolder bdHolder=delegate.parseBeanDefinitionElement(ele);
delegate:BeanDefinitionParserDelegate该类主要是完成对于element的解析工作,位于org.springframework.beans.factory.xml包下
public BeanDefinitionHolder parseBeanDefinitionElement(Elementele){
returnparseBeanDefinitionElement(ele, null);
}
该方法提供解析element,如果解析出错会返回一个null。
它调用如下的方法进行解析,string id ID_ATTRIBUTE 指的是常亮字符“id”<bean id>这里面的,name也是类似。
public BeanDefinitionHolder parseBeanDefinitionElement(Elementele,BeanDefinition containingBean) {
//对应id name 等标签
Stringid = ele.getAttribute(ID_ATTRIBUTE);
StringnameAttr= ele.getAttribute(NAME_ATTRIBUTE);
List<String>aliases= newArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[]nameArr= StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
StringbeanName= id;
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) {
checkNameUniqueness(beanName, aliases, ele);
}
//解析的BeanDefinition放到GenericBeanDefintion中
AbstractBeanDefinitionbeanDefinition= parseBeanDefinitionElement(ele, beanName,containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName =BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
StringbeanClassName= 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);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
(a)其中调用spring框架中的StringUtils类,并使用Java.util.StringTokenizer类进行字符串分割获得有用数据,然后添加到alisases:list中;
(b)先删除掉该beanName(id),然后再检测在当前的beandefinition nest中没有使用该bean,然后解析。
(c) AbstractBeanDefinition beanDefinition =parseBeanDefinitionElement(ele, beanName,containingBean);
获得一个beandefinition,只不过这里将该对象引用给了它的抽象的父类,
该方法首先是
This.parseState.push(newBeanEntry(beanName));
new BeanEntry(String beanName)是beanEntry的一个构造方法,该类主要表示一个BeanDefinition 。
BeanDefinition是一个接口,其中定义了一些在xml中,bean<bean>定义的标签的对应的属性,其中有我们熟悉的lazyInit,
public interfaceBeanDefinition extends AttributeAccessor, BeanMetadataElement {
StringSCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
StringSCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT= 1;
int ROLE_INFRASTRUCTURE= 2;
StringgetParentName();
void setParentName(String parentName);
StringgetBeanClassName();
void setBeanClassName(StringbeanClassName);
StringgetFactoryBeanName();
voidsetFactoryBeanName(String factoryBeanName);
StringgetFactoryMethodName();
voidsetFactoryMethodName(String factoryMethodName);
StringgetScope();
void setScope(String scope);
boolean isLazyInit();
void setLazyInit(boolean lazyInit);
String[]getDependsOn();
void setDependsOn(String[] dependsOn);
boolean isAutowireCandidate();
void setAutowireCandidate(boolean autowireCandidate);
boolean isPrimary();
void setPrimary(boolean primary);
ConstructorArgumentValuesgetConstructorArgumentValues();
MutablePropertyValuesgetPropertyValues();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
int getRole();
StringgetDescription();
StringgetResourceDescription();
BeanDefinitiongetOriginatingBeanDefinition();
}
AbstractBeanDefintion则是对于BeanDefinition接口的实现类,实现了其中操作属性的方法,可以将<bean> 中属性加载到该类中,是xml文件的一种对象转换。
之后className = ele.getAttribute(CLASS_ATTRIBUTE).trim();获得其classname.
并获得其父类string parent,然后用
AbstractBeanDefinition db =creatBeanDefinition(className,parent);
创建出beandefinition,该create方法则是利用了BeanDefinitionReaderUitls工具类的createBeanDefinition(parentName,className,this.readerContext.getBeanClassLoader())实现的,具体如下:
public staticAbstractBeanDefinitioncreateBeanDefinition(
StringparentName,String className,ClassLoader classLoader)throwsClassNotFoundException {
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;
}
之后是:
public AbstractBeanDefinition parseBeanDefinitionElement(
Elementele,String beanName,BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
StringclassName= null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)){
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
Stringparent= null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)){
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
AbstractBeanDefinitionbd =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;
}……
接着是如上的解析beandefinition的属性,设置description,解析metaelements,并且解析subElements,解析替代方法子元素parseReplacedMethodSubElements,解析构造器中参数elements,解析属性elements,设置资源等等。
然后返回到parseBeanDefinitionElement():,这些解析的具体的内容可以参考郝佳编著的《spring源码深度解析》中第三章的内容。BeanDefintionParseDelegate中继续执行,
最后将这个beandefinition和beanname都放到beandefinitionholder中,返回。即返回到DefaultBeanDefinitionDocumentReader类下的processBeanDefintion()方法。
(2) 对于holder进行修饰(装饰)
bdHolder= delegate.decorateBeanDefinitionIfRequired(ele,bdHolder);
里面利用了NamespaceHandler,命名空间的修饰,是不是默认的标签还是用户自定义的,可以通过其内容之进行判断。默认的标志为"http://www.springframework.org/schema/beans"
,其他用户自定义的标签由相应的NamespaceHandler进行处理。
(3) 注册最终的装饰后的bdholder类,
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,getReaderContext().getRegistry());
使用相应的beandefinitionfactory进行相应的holder注册
public staticvoidregisterBeanDefinition(
BeanDefinitionHolderdefinitionHolder,BeanDefinitionRegistry registry)
throwsBeanDefinitionStoreException {
// Register bean definition under primary name.
StringbeanName= definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[]aliases= definitionHolder.getAliases();
if (aliases != null) {
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}
DefaultListBeanFactory中有一个实现了registryBeanDefinition()的方法,可以参考。一种是通过beanName注册,另外一种是通过alias别名进行注册。
beanName注册是将BeanName和BeanDefinition一起以Map <key value>形式加入到BeanDefintionMap中,其步骤为
(a1)进行一些验证(方法属性是否有);
(a2)然后判断是否可以覆盖,不可则抛出异常;
(a3)然后添加beanName到map中;
(a4)最后则是重置所有对应的缓存。
存在于DefaultListableBeanFactory中:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throwsBeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceofAbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
}
catch(BeanDefinitionValidationException ex) {
throw newBeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinitionoldBeanDefinition;
synchronized (this.beanDefinitionMap){
oldBeanDefinition= this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition!= null){
if (!this.allowBeanDefinitionOverriding) {
throw newBeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition+ "] for bean '" + beanName+
"': There is already ["+ oldBeanDefinition+ "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName+
"': replacing ["+ oldBeanDefinition+ "] with [" + beanDefinition+ "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames= null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
if (oldBeanDefinition!= null|| containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
通过alias别名注册的情况则是SimpleAliasRegistry中的实现了该方法:
public voidregisterAlias(String name, String alias){
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
if (alias.equals(name)) {
this.aliasMap.remove(alias);
}
else {
if(!allowAliasOverriding()) {
StringregisteredName= this.aliasMap.get(alias);
if (registeredName != null && !registeredName.equals(name)) {
throw new IllegalStateException("Cannot register alias '" + alias+ "' for name '" +
name + "': It is already registered for name '" + registeredName+ "'.");
}
}
checkForAliasCircle(name, alias);
this.aliasMap.put(alias, name);
}
}
(b1)如果有alias别名和beanName相同的先从aliasmap中移除,
(b2)如果不允许相同别名的覆盖,则会抛出异常
(b3)检查是否有循环的情况A->B ,A->C->B的情况
(b4)将alias和name添加到别名map中
(4)注册事件传递(注册监听)// Send registration event.
getReaderContext().fireComponentRegistered(newBeanComponentDefinition(bdHolder));
readercontext中注册该监听事件
public voidfireComponentRegistered(ComponentDefinitioncomponentDefinition){
this.eventListener.componentRegistered(componentDefinition);
}
其中的参数可以是如下构造,显示本身,然后是内部的beandefinition和参考设置。
public BeanComponentDefinition(BeanDefinitionHolderholder){
super(holder);
findInnerBeanDefinitionsAndBeanReferences(holder.getBeanDefinition());
}