前言
上篇文章我们讲到了processBeanDefinition(ele, delegate) 方法的源码:
//此方法需要两个参数:1.在之前解析的子节点element,2.解析器
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//此处将element对象解析成BeanDefinitionHolder对象,这个BeanDefinitionHolder就相当于对BeanDefinition做了一层包装。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//如果bean标签中嵌套了自定义标签,那么就会经过此方法解析,对element进行再次解析,并封装成最终的bdHolder
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//此处是注册BeanDdfinition,用BeanDefinitionReaderUtils工具类进行注册,并存储在一个Map中。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 此处是发布事件:整个spring容器注册完成之后,发布事件,通知spring容器,spring监听此事件,如果监听到了,进行后续处理
//但是此方法是个空方法,这是spring容器给开发者留的一个扩展点。
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
这篇文章我们详细讲解一下这个源码中的 将element对象解析成BeanDefinitionHolder对象的过程
解析element对象,包装成BeanDefinitionHolder对象
展开讲解BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele) 的源码:
//先调用这里,然后走其重载方法
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
//这是核心方法:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//获取别名,name属性可以定义多个值(以 逗号/分号 分隔),而只有第一个值会当作name的值,其余的值,会被当做别名处理
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
//如果没有id属性,且别名不为空,那么就取别名的第一个值,作为bean的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");
}
}
//containingBean是这个方法的重载方法调用,所以containingBean肯定为null,
//此代码块的作用是检验beanName是否是唯一的。
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//这里是真正封装beanDefinition的逻辑。此处是核心代码。上面只解决了id和name的标签,还有很多其他标签,就是在此解决的。
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
//下面这个if块是beanName没有的情况执行的,出现这种情况的原因是,<bean>标签中既没有id属性,也没有name属性。这种情况就按照自己默认算法帮忙生成一个
if (!StringUtils.hasText(beanName)) {
try {
//此if块肯定不执行,执行else代码块
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
} else {
//
beanName = this.readerContext.generateBeanName(beanDefinition);
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);
//将BeanDefinition对象包装一层,返回一个BeanDefinitionHolder 对象。
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
接下来展开讲解AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean)源码:
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable 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);
}
try {
//这里创建了一个基本为空的BeanDefinition,实际创建的是其实现类 GenericBeanDefinition
//这里同时也set其父类的名字和set自己类的信息
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//这里解析了大部分的标签:singleton、scope、abstract、lazy-init、autowire、depends-on、primary、init-method 等等
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//添加一些说明文字
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//
parseMetaElements(ele, bd);
//这里解析lookup-method 标签,look-up method方法查找
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//这里解析replaced-method 标签,replace method方法替换
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//这里解析constructor-arg 标签
parseConstructorArgElements(ele, bd);
//这里解析property 标签,这个里面需要注意的是,spring将所有的property标签封装到了BeanDefinition中的PropertyValues属性中。
parsePropertyElements(ele, bd);
//这里解析qualifier 标签
parseQualifierElements(ele, bd);
//这里set源文件xml
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;
}
将BeanDefinitionHolder对象进行注册(存储)
接下来讲解BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()) 源码:
//这个方法有两个参数:
//definitionHolder:这个就是被包装了一层的BeanDefinition对象
//registry:注册器
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
//获取bean的名字
String beanName = definitionHolder.getBeanName();
//通过注册器,将BeanDefinition存储起来,此处是核心
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
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 {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//此if块是做安全校验用的,不重要,略过
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//这里是判断这个beanName是否已经注册过
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
//如果不为空,那就注册过。然后这里做一些相应的处理,不重要
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//此处校验这个工厂的bean是否已经开始进行注册阶段了,显然这里是还没有开始,所以会走else块,if块没啥用
if (hasBeanCreationStarted()) {
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 {
//注册/存储BeanDefinition,此处也是最关键的
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
总结:
本片文章讲解了Spring默认标签的解析 ,构建,注册
下一篇文章我们将讲解Spring创建对象的流程