[Spring3.x源码]IoC(二)解析XML建立上下文

AbstractApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");完成XML的解析与上下文对象的实例化

1.FileSystemXmlApplicationContext

	public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}
2.refresh()在其父类AbstractApplicationContext中
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}
		
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}
3.refreshBeanFactory来自AbstractRefreshableApplicationContext中
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//返回的是DefaultListableBeanFactory对象
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
	
	protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}
4.loadBeanDefinitions(beanFactory);来自AbstractXmlApplicationContext
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, 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.setEnvironment(this.getEnvironment());
		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);
	}
	
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}
5.reader.loadBeanDefinitions(configLocations);来自XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int counter = 0;
		for (String location : locations) {
			counter += loadBeanDefinitions(location);
		}
		return counter;
	}
	
	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}
	
	public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int loadCount = loadBeanDefinitions(resources);
				if (actualResources != null) {
					for (Resource resource : resources) {
						actualResources.add(resource);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
				}
				return loadCount;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
			int loadCount = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
			}
			return loadCount;
		}
	}
6.loadBeanDefinitions(resources);来自XmlBeanDefinitionReader
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));
	}
	
	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
	
	↑↑↑return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){}
			int validationMode = getValidationModeForResource(resource);
			Document doc = this.documentLoader.loadDocument(
					inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
			return registerBeanDefinitions(doc, resource);
			
	
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//documentReader对象的类:DefaultBeanDefinitionDocumentReader
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(this.getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
		//createReaderContext返回的对象类:XmlReaderContext
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
7.documentReader.registerBeanDefinitions(doc, createReaderContext(resource));来自DefaultBeanDefinitionDocumentReader类
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;

		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();

		doRegisterBeanDefinitions(root);
	}
	protected void doRegisterBeanDefinitions(Element root) {
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		if (StringUtils.hasText(profileSpec)) {
			Assert.state(this.environment != null, "environment property must not be null");
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec,
						BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			if (!this.environment.acceptsProfiles(specifiedProfiles)) {
				return;
			}
		}

		// any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.
		BeanDefinitionParserDelegate parent = this.delegate;
		//返回BeanDefinitionParserDelegate对象
		this.delegate = createHelper(readerContext, root, parent);

		preProcessXml(root);
		//会调用parseDefaultElement(ele, delegate);处理bean节点
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}
	
	/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					//判断节点是否属于默认的命名空间delegate.isDefaultNamespace(ele),像<bean>节点就是属于默认的命名空间
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		//解析<bean>标签
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}
	
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
8.BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);调用BeanDefinitionParserDelegate中的方法创建BeanDefinition类用于保存配置信息
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {}
	
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {}		
	
	public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
			public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, BeanDefinition containingBean) {

			this.parseState.push(new BeanEntry(beanName));
	
			String className = null;
			if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
				className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
			}
	
			try {
				String parent = null;
				if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
					parent = ele.getAttribute(PARENT_ATTRIBUTE);
				}
				//返回GenericBeanDefinition对象,然后解析ele节点下的相关节点信息保存到其中。
				AbstractBeanDefinition bd = createBeanDefinition(className, parent);
				//解析节点的信息,如SINGLETON_ATTRIBUTE、ABSTRACT_ATTRIBUTE、LAZY_INIT_ATTRIBUTE、INIT_METHOD_ATTRIBUTE等等。
				parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
				bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
	
				parseMetaElements(ele, bd);
				parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
				parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
				//解析Constructor-arg节点
				parseConstructorArgElements(ele, bd);
				//解析property节点
				parsePropertyElements(ele, bd);
				parseQualifierElements(ele, bd);
	
				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;
		}
	
		public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			BeanDefinition containingBean, AbstractBeanDefinition bd){}
		
		public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
			NodeList nl = beanEle.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
					parsePropertyElement((Element) node, bd);
				}
			}
		}
		
		public void parsePropertyElement(Element ele, BeanDefinition bd) {
			String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
			if (!StringUtils.hasLength(propertyName)) {
				error("Tag 'property' must have a 'name' attribute", ele);
				return;
			}
			this.parseState.push(new PropertyEntry(propertyName));
			try {
				if (bd.getPropertyValues().contains(propertyName)) {
					error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
					return;
				}
				Object val = parsePropertyValue(ele, bd, propertyName);
				PropertyValue pv = new PropertyValue(propertyName, val);
				parseMetaElements(ele, pv);
				pv.setSource(extractSource(ele));
				bd.getPropertyValues().addPropertyValue(pv);
			}
			finally {
				this.parseState.pop();
			}
		}
		
		public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
			String elementName = (propertyName != null) ?
							"<property> element for property '" + propertyName + "'" :
							"<constructor-arg> element";

			// Should only have one child element: ref, value, list, etc.
			NodeList nl = ele.getChildNodes();
			Element subElement = null;
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
						!nodeNameEquals(node, META_ELEMENT)) {
					// Child element is what we're looking for.
					if (subElement != null) {
						error(elementName + " must not contain more than one sub-element", ele);
					}
					else {
						subElement = (Element) node;
					}
				}
			}
			//不允许ref和value属性同时存在
			boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
			boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
			if ((hasRefAttribute && hasValueAttribute) ||
					((hasRefAttribute || hasValueAttribute) && subElement != null)) {
				error(elementName +
						" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
			}
			//有ref属性
			if (hasRefAttribute) {
				String refName = ele.getAttribute(REF_ATTRIBUTE);
				if (!StringUtils.hasText(refName)) {
					error(elementName + " contains empty 'ref' attribute", ele);
				}
				RuntimeBeanReference ref = new RuntimeBeanReference(refName);
				ref.setSource(extractSource(ele));
				return ref;
			}//有value属性
			else if (hasValueAttribute) {
				TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
				valueHolder.setSource(extractSource(ele));
				return valueHolder;
			}
			else if (subElement != null) {
				return parsePropertySubElement(subElement, bd);
			}
			else {
				// Neither child element nor "ref" or "value" attribute found.
				error(elementName + " must specify a ref or value", ele);
				return null;
			}
		}
9.至此,配置信息已经保存到GenericBeanDefinition类中。回到DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate )中:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());将这个配置信息类注册到DefaultListableBeanFactory类中。
		public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

			// Register bean definition under primary name.
			String beanName = definitionHolder.getBeanName();
			//registry为XmlBeanDefinitionReader的registry,来自其构造函数DefaultListableBeanFactory对象
			registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
	
			// Register aliases for bean name, if any.
			String[] aliases = definitionHolder.getAliases();
			if (aliases != null) {
				for (String aliase : aliases) {
					registry.registerAlias(beanName, aliase);
				}
			}
		}
10.registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());来自DefaultListableBeanFactory

	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 (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		synchronized (this.beanDefinitionMap) {
			Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
			if (oldBeanDefinition != null) {
				if (!this.allowBeanDefinitionOverriding) {
					throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
							"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
							"': There is already [" + oldBeanDefinition + "] bound.");
				}
				else {
					if (this.logger.isInfoEnabled()) {
						this.logger.info("Overriding bean definition for bean '" + beanName +
								"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
					}
				}
			}
			else {
				this.beanDefinitionNames.add(beanName);
				this.frozenBeanDefinitionNames = null;
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);

			resetBeanDefinition(beanName);
		}
	}
<bean>配置信息BeanDefinition保存在DefaultListableBeanFactory.beanDefinitionMap属性中,DefaultListableBeanFactory又保存在context的属性对象beanFactory中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值