在上一篇中写了spring是如何定位资源的,现在我们有了Resource
,下一步就是将其解析为BeanDefinition
什么是BeanDefinition
可以将BeanDefinition看成是Bean的抽象,里面放了一个Bean的基本信息,比如类名,依赖,构造方法等,spring就是通过这些信息来实例化Bean的
spring完成资源定位后,开始执行loadBeanDefinitions(Resource...)
方法处理资源,一路追踪进去可以看到XmlBeanDefinitionReader#doLoadBeanDefinitions
方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
可以看到BeanDefinition的载入分成两部分
第一步xml解析成Document
(使用java自带的Xerces解析xml)
第二步将Document
解析为BeanDefinition
将xml解析为Document
在XmlBeanDefinitionReader#doLoadDocument
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
具体的解析过程就不说了,有兴趣的可以深入了解,重点说下spring是如何将Document
解析为BeanDefinition
的
从registerBeanDefinitions
方法进入,一路到DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
里面根据是否为自定义元素分别调用了parseCustomElement
和parseDefaultElement
方法
这里我们只需要分析对默认元素的处理即parseDefaultElement
方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
///解析别名
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)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
我们最常用的<bean>标签,运行的是processBeanDefinition
方法
BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element, String,BeanDefinition)
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);
//解析bean的属性比如lazy-init,scope
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) {
}
finally {
this.parseState.pop();
}
return null;
}
到这一步就获得了BeanDefinition
对象,默认使用的是GenericBeanDefinition
,最后我们传递的并不是这个对象而是再次包装成BeanDefinitionHolder
BeanDefinitionHolder主要比BeanDefinition多了aliases属性
得到BeanDefinition
之后并不能马上使用还需要注册
BeanDefinition注册调用过程如下图
时序图DefaultListableBeanFactory#registerBeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//省略代码
BeanDefinition oldBeanDefinition;
//判断是否已经实例化了该bean
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
//省略代码
}
else {
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<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
}
}
其核心就是将BeanDefinition
放入了一个Map中,以供以后实例化Bean,到这一步就算是注册完成了,下一篇讲解如何实例化Bean
网友评论