Bean 配置信息中的<import>和<alias>元素解析在DefaultBeanDefinitionDocumentReader 中已经完成,对Bean 配置信息中使用最多的<bean>元素交由BeanDefinitionParserDelegate 来解析,其解析实现的源码如下:

//解析<Bean>元素的入口
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {return parseBeanDefinitionElement(ele, null);
}//解析Bean定义资源文件中的<Bean>元素,这个方法中主要处理<Bean>元素的id,name和别名属性
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {//获取<Bean>元素中的id属性值String id = ele.getAttribute(ID_ATTRIBUTE);//获取<Bean>元素中的name属性值String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//获取<Bean>元素中的alias属性值List<String> aliases = new ArrayList<>();//将<Bean>元素中的所有name属性值存放到别名中if (StringUtils.hasLength(nameAttr)) {String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);aliases.addAll(Arrays.asList(nameArr));}String beanName = id;//如果<Bean>元素中没有配置id属性时,将别名中的第一个值赋值给beanNameif (!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");}}//检查<Bean>元素所配置的id或者name的唯一性,containingBean标识<Bean>//元素中是否包含子<Bean>元素if (containingBean == null) {//检查<Bean>元素所配置的id、name或者别名是否重复checkNameUniqueness(beanName, aliases, ele);}//详细对<Bean>元素中配置的Bean定义进行解析的地方AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);if (beanDefinition != null) {if (!StringUtils.hasText(beanName)) {try {if (containingBean != null) {//如果<Bean>元素中没有配置id、别名或者name,且没有包含子元素//<Bean>元素,为解析的Bean生成一个唯一beanName并注册beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);}else {//如果<Bean>元素中没有配置id、别名或者name,且包含了子元素//<Bean>元素,为解析的Bean使用别名向IOC容器注册beanName = this.readerContext.generateBeanName(beanDefinition);// Register an alias for the plain bean class name, if still possible,// if the generator returned the class name plus a suffix.// This is expected for Spring 1.2/2.0 backwards compatibility.//为解析的Bean使用别名注册时,为了向后兼容//Spring1.2/2.0,给别名添加类名后缀String beanClassName = 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);}//当解析出错时,返回nullreturn null;
}protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {String foundName = null;if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {foundName = beanName;}if (foundName == null) {foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases);}if (foundName != null) {error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);}this.usedNames.add(beanName);this.usedNames.addAll(aliases);
}//详细对<Bean>元素中配置的Bean定义其他属性进行解析
//由于上面的方法中已经对Bean的id、name和别名等属性进行了处理
//该方法中主要处理除这三个以外的其他属性数据
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {//记录解析的<Bean>this.parseState.push(new BeanEntry(beanName));//这里只读取<Bean>元素中配置的class名字,然后载入到BeanDefinition中去//只是记录配置的class名字,不做实例化,对象的实例化在依赖注入时完成String className = null;//如果<Bean>元素中配置了parent属性,则获取parent属性的值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 {//根据<Bean>元素配置的class名称和parent属性值创建BeanDefinition//为载入Bean定义信息做准备AbstractBeanDefinition bd = createBeanDefinition(className, parent);//对当前的<Bean>元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);//为<Bean>元素解析的Bean设置description信息bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));//对<Bean>元素的meta(元信息)属性解析parseMetaElements(ele, bd);//对<Bean>元素的lookup-method属性解析parseLookupOverrideSubElements(ele, bd.getMethodOverrides());//对<Bean>元素的replaced-method属性解析parseReplacedMethodSubElements(ele, bd.getMethodOverrides());//解析<Bean>元素的构造方法设置parseConstructorArgElements(ele, bd);//解析<Bean>元素的<property>设置parsePropertyElements(ele, bd);//解析<Bean>元素的qualifier属性parseQualifierElements(ele, bd);//为当前解析的Bean设置所需的资源和依赖对象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();}//解析<Bean>元素出错时,返回nullreturn null;
}

只要使用过Spring,对Spring 配置文件比较熟悉的人,通过对上述源码的分析,就会明白我们在Spring配置文件中<Bean>元素的中配置的属性就是通过该方法解析和设置到Bean 中去的。

注意:在解析<Bean>元素过程中没有创建和实例化Bean 对象,只是创建了Bean 对象的定义类BeanDefinition,将<Bean>元素中的配置信息设置到BeanDefinition 中作为记录,当依赖注入时才使用这些记录信息创建和实例化具体的Bean 对象。

上面方法中一些对一些配置如元信息(meta)、qualifier 等的解析,我们在Spring 中配置时使用的也不多,我们在使用Spring 的<Bean>元素时,配置最多的是<property>属性,因此我们下面继续分析源码,了解Bean 的属性在解析时是如何设置的。

基于Xml 的IOC 容器-载入<bean>元素相关推荐

  1. 基于Xml 的IOC 容器-载入<list>的子元素

    在BeanDefinitionParserDelegate 类中的parseListElement()方法就是具体实现解析<property>元素中的<list>集合子元素,源 ...

  2. 基于Xml 的IOC 容器-载入<property>的子元素

    在BeanDefinitionParserDelegate 类中的parsePropertySubElement()方法对<property>中的子元素解析,源码如下: //解析<p ...

  3. 基于Xml 的IOC 容器-载入<property>元素

    BeanDefinitionParserDelegate 在解析<Bean>调用parsePropertyElements()方法解析<Bean>元素中的<propert ...

  4. 基于Xml 的IOC 容器-载入配置路径

    AbstractRefreshableApplicationContext 中只定义了抽象的loadBeanDefinitions 方法,容器真正调用的是其子类AbstractXmlApplicati ...

  5. 一步一步手绘Spring IOC运行时序图二(基于XML的IOC容器初始化)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  6. 从源码深处体验Spring核心技术--基于Xml的IOC容器的初始化

    IOC 容器的初始化包括 BeanDefinition 的 Resource 定位.加载和注册这三个基本的过程. 我们以ApplicationContext 为例讲解,ApplicationConte ...

  7. 基于Xml 的IOC 容器-开始启动

    SpringIOC 容器对Bean 配置资源的载入是从refresh()函数开始的,refresh()是一个模板方法,规定了IOC 容器的启动流程, 有些逻辑要交给其子类去实现.它对Bean 配置资源 ...

  8. 基于Xml 的IOC 容器-分配解析策略

    XmlBeanDefinitionReader 类中的doLoadBeanDefinition()方法是从特定XML 文件中实际载入Bean 配置资源的方法,该方法在载入Bean 配置资源之后将其转换 ...

  9. 基于Xml 的IOC 容器-创建容器

    obtainFreshBeanFactory()方法调用子类容器的refreshBeanFactory()方法,启动容器载入Bean 配置信息的过程,代码如下: protected Configura ...

最新文章

  1. (2) 第二章 WCF服务与数据契约 服务契约详解(二)- 如何引用WCF提供的服务
  2. mysql 定时计划_MYSQL定时任务
  3. AVG Anti-Spyware 7.5 .0.50(原EWIDO)汉化 破解 注册 序列号
  4. Mysql 面试常问4 -- 锁模块之事务并发访问产生的问题以及事务隔离机制 InnoDB支持事务
  5. Linux MySQL单实例源码编译安装5.6
  6. Linux挂载iso文件步骤
  7. 【vim环境配置】解决ubuntu上 由YouCompleteMe插件配置不当引起的 自动补全失效的问题
  8. 阿里+北大 | 在梯度上做简单mask竟有如此的神奇效果
  9. 在线swf转html,swf转换器
  10. 谭浩强《c语言程序设计》第四版--重点难点总结
  11. 用云真机测试本地应用程序
  12. python数据分析 - 卡方检验
  13. 电影TS/TC/SCR/R5/BD/HD/HC版本意思收集(转)
  14. 昭阳k20-80拆机过程
  15. 面向对象与面向过程(尚学堂视频学习总结_001)
  16. 在Unity 2018中充分使用TextMesh Pro
  17. “三天打鱼,两天晒网”
  18. oracle+获取最后一行数据库,获取表最后一条数据
  19. 笔记本连不上苹果手机热点怎么回事
  20. 微信公众号上传图片功能

热门文章

  1. 2019.6.18 校内测试 分析+题解
  2. mysql 互为主从复制常见问题
  3. 【编程题目】输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。...
  4. 第6节 三个败家子(6)——很黄很暴力的刘禅
  5. 从网上发现的经典js脚本
  6. 【centos7】添加开机启动服务/脚本
  7. 降低成本,提高生产力—8句话讲清RPA的部署
  8. time模块及datetime模块常用方法讲解
  9. mongodb创建用户和密码
  10. 【Todo】Tomcat与Jetty的比较 以及Tomcat架构的学习