默认标签的解析是在parseDefaultElement中:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele); //处理import标签
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele); //处理alias标签
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate); //处理bean标签
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
doRegisterBeanDefinitions(ele); //处理beans标签
}
}
分析对bean标签的解析及注册:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
1,首先委托BeanDefinitionDelegate类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder类实例bdHolder,此时bdHolder实例中已经包含了配置文件中的各种属性,如class、name、id、alias.
2,当返回的bdHolder不为空时,若存在默认标签的子节点下再有自定义属性,还需再次对自定义标签进行解析.
3,注册bdHolder
4,发出响应事件,通知相关的监听器,这个bean已经加载完成.
以下是每一步的具体分析(代码多有删减,只保留关键处):
===========================================================
一,返回包含各种配置属性的BeanDefinitionHolder实例bdHolder
public class BeanDefinitionParserDelegate {
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//解析id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//解析name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//分隔name属性......
//进一步解析其他属性并统一封装到GenericBeanDefinition类型的实例中
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
//若检测到bean没有指定beanName,那么使用默认规则为此bean生成beanName
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
//将获取到的信息封装到BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
public class BeanDefinitionParserDelegate {
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//解析class属性
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
//解析parent属性
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
//创建用于承载各种属性的AbstractBeanDefinition子类GenericBeanDefinition的实例
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//硬编码解析默认bean的各种属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//提取description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析元数据
parseMetaElements(ele, bd);
//解析lookup-method属性
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析replaced-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;
BeanDefinition是AbstractBeanDefinition的接口.
spring通过BeanDefinition将配置文件中的bean配置信息转换为容器的内部表示,并将这些BeanDefinition注册到BeanDefinitionRegistry中。
spring的BeanDefinitionRegistry就像是spring配置信息的内存数据库,主要是以map的形式保存;后续操作直接从BeanDefinitionRegistry中读取配置信息.
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName) {
return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
}
public class BeanDefinitionReaderUtils {
public static AbstractBeanDefinition createBeanDefinition(String parentName, String className, ClassLoader classLoader) {
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;
}
有了承载各种属性的BeanDefinition实例了,可以进行各种属性的解析了.
scope、singleton、abstract、lazy-init、autowire、dependency-check、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、
factory-bean属性等.
meta属性用作额外的声明;
lookup-method获取器注入,把一个方法声明为返回某种类型的bean,但实际要返回的bean是在配置文件里面配置.
replace-method方法替换,可以在运行时用新的方法替换现有的方法.
=============================================
解析默认标签中的自定义类型属性:
public class BeanDefinitionParserDelegate {
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = definitionHolder;
NamedNodeMap attributes = ele.getAttributes();
//遍历所有属性,看看是否有适用于修饰的属性
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
NodeList children = ele.getChildNodes();
//遍历所有的子节点,看看是否有适用于修饰的子元素
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
//获得自定义标签的命名空间
String namespaceUri = getNamespaceURI(node);
//对于非默认标签的进行修饰
if (!isDefaultNamespace(namespaceUri)) {
//根据命名空间找到对应的处理器
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler != null) {
//进行修饰
return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
}
}
return originalDef;
}
====================================================
注册解析的BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
public class BeanDefinitionReaderUtils {
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry){
//使用beanName做唯一标识注册
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//注册所有别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
//注册前最后一次校验,校验methodOverrides
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
//抛异常
}
}
//处理已经注册beanName的情况
//记录beanName
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
//注册beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
resetBeanDefinition(beanName); //重置所有beanName对应的缓存
}
public class SimpleAliasRegistry implements AliasRegistry {
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
public void registerAlias(String name, String alias) {
if (alias.equals(name)) {
this.aliasMap.remove(alias); //若beanName与alias相同的话不记录alias,并删除对应的alias
}
else {
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
if (registeredName.equals(name)) {
return;
}
if (!allowAliasOverriding()) {
//若alias不允许被覆盖则抛异常
}
}
checkForAliasCircle(name, alias);
//注册alias
this.aliasMap.put(alias, name);
}
}
====================================================
通知监听器解析及注册完成
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
此实现只为扩展,当需要对注册BeanDefinition事件进行监听时,可以通过注册监听器的方式将处理逻辑写入监听器中.
=================================
=================================
alias、import及beans标签和bean标签的解析大同小异.