spring解析xml生成BeanDefinition的过程

        毫无疑问,spring的核心是bean,一个简单的获取bean的过程如下:

    ClassPathResource resource = new ClassPathResource("services.xml");
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader =  new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(resource);
    SayService sayService  = (SayService)factory.getBean("sayService");

        services.xml就是spring的[配置文件,sayService就是配置文件里面配置的bean.

 

        spring生成bean并不是一气呵成,因为bean之间是有相互依赖关系的.只能先把xml都解析完后才能生成最终需要调用的bean.BeanDefinition就是配置文件与最终生成bean之间的桥梁.本文主要分析spring如何解析bean的配置文件到生成包含bean元信息对象BeanDefinition的过程.下面是这个过程的一个简单的时序图:

            
spring解析xml生成BeanDefinition的过程_第1张图片
 

 
spring解析xml生成BeanDefinition对象的过程主要涉及XmlBeanDefinitionReader,DocumentLoader,DefaultBeanDefinitionDocumentReader,BeanDefinitionParserDelegate,DefaultListableBeanFactory这几个类,几个类的职责分别是:
1. XmlBeanDefinitionReader根据xml的文件路径生成InputStream对象,进而得到InputStream的xml的包装类InputSource对象.
2. DocumentLoader解析InputSource得到Document对象.
3. DefaultBeanDefinitionDocumentReader类委托BeanDefinitionParserDelegate类解析Document对象生成BeanDefinition对象,BeanDefinition对象中包含xml中配置的bean的元信息.
4.生成的BeanDefinition对象最终都会注册到DefaultListableBeanFactory,供后续生成bean对象使用.

 spring的配置文件中bean的配置元素id和name的关系

          一个bean可以同时配置id,name.name里面 可以配置多个名称,多个名称之间可以重复, 名称之间用逗号隔开,如果没有配置id,默认名称的第一作为id.并且整个容器不同bean之间不能有相同的id和name,spring在解析xml配置文件时会有校验,校验代码如下:

         

	protected void checkNameUniqueness(String beanName, List aliases, Element beanElement) {
		String foundName = null;

		if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
			foundName = beanName;
		}
		if (foundName == null) {
			foundName = (String) CollectionUtils.findFirstMatch(this.usedNames, aliases);
		}
		if (foundName != null) {
			error("Bean name '" + foundName + "' is already used in this file", beanElement);
		}

		this.usedNames.add(beanName);
		this.usedNames.addAll(aliases);
	}

  

    在调用getBean(String name)方法时,会将name转换为id,具体代码如下:

     

	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing.
		String resolvedName = null;
		do {
			resolvedName = (String) this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

}

 

 

 

你可能感兴趣的:(Spring)