毫无疑问,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对象的过程主要涉及到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; } }
扫描二维码关注公众号,回复:
684065 查看本文章