Spring2.0中的IOC随笔(二)之配置文件解析
在Web应用中,默认的bean配置文件为WEB-INF目录下面的applicationContext.xml文件(当然你也可以指定其他路径或文件名),而对配置文件的加载是在XmlWebApplicationContext中实现的,该bean容器将具体的加载工作全权委托给了一个名为XmlBeanDefinitionReader的辅助类,同时创建了一个新的Bean工厂DefaultListableBeanFactory作为参数传给了其构造函数,供其调用该Bean工厂中提供的服务,代码如下:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {// Support old XmlBeanDefinitionParser SPI for backwards-compatibility.if (this.parserClass != null) {XmlBeanDefinitionParser parser =(XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);return parser.registerBeanDefinitions(this, doc, resource);}// Read document based on new BeanDefinitionDocumentReader SPI.BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();int countBefore = getBeanFactory().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getBeanFactory().getBeanDefinitionCount() - countBefore;}public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;logger.debug("Loading bean definitions");Element root = doc.getDocumentElement();BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);preProcessXml(root);parseBeanDefinitions(root, delegate);postProcessXml(root);}public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {String className = null;if (ele.hasAttribute(CLASS_ATTRIBUTE)) {className = ele.getAttribute(CLASS_ATTRIBUTE);}String parent = null;if (ele.hasAttribute(PARENT_ATTRIBUTE)) {parent = ele.getAttribute(PARENT_ATTRIBUTE);}try {this.parseState.push(new BeanEntry(beanName));AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(parent, className, getReaderContext().getReader().getBeanClassLoader());if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {// Spring 2.0 "scope" attributebd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {error("Specify either 'scope' or 'singleton', not both", ele);}}else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {// Spring 1.x "singleton" attributebd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));}else if (containingBean != null) {// Take default from containing bean in case of an inner bean definition.bd.setSingleton(containingBean.isSingleton());}if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));}String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {// Just apply default to singletons, as lazy-init has no meaning for prototypes.lazyInit = getDefaultLazyInit();}bd.setLazyInit(TRUE_VALUE.equals(lazyInit));if (ele.hasAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE)) {bd.setAutowireCandidate(TRUE_VALUE.equals(ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE)));}String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);if (DEFAULT_VALUE.equals(autowire)) {autowire = getDefaultAutowire();}bd.setAutowireMode(getAutowireMode(autowire));String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);if (DEFAULT_VALUE.equals(dependencyCheck)) {dependencyCheck = getDefaultDependencyCheck();}bd.setDependencyCheck(getDependencyCheck(dependencyCheck));if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));}if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));}if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));}if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);if (!"".equals(initMethodName)) {bd.setInitMethodName(initMethodName);}}else {if (getDefaultInitMethod() != null) {bd.setInitMethodName(getDefaultInitMethod());bd.setEnforceInitMethod(false);}}if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);if (!"".equals(destroyMethodName)) {bd.setDestroyMethodName(destroyMethodName);}}else {if (getDefaultDestroyMethod() != null) {bd.setDestroyMethodName(getDefaultDestroyMethod());bd.setEnforceDestroyMethod(false);}}parseMetaElements(ele, bd);parseLookupOverrideSubElements(ele, bd.getMethodOverrides());parseReplacedMethodSubElements(ele, bd.getMethodOverrides());parseConstructorArgElements(ele, bd);parsePropertyElements(ele, bd);bd.setResourceDescription(getReaderContext().getResource().getDescription());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;}