Spring源码(二)— AbstractApplicationContext(续)- 解析xml文件

上一篇中,已经创建环境对象(StandardEnvironment)以及解析了给定的xml文件路径。
本篇会着重讲解后续的refresh()方法,在这个方法中,会创建更为重要的BeanFactory和解析XML文件。

refresh

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			/**
				1. 设置容器开始时间
				2. 设置激活标志位
				3. 设置关闭标志位
				4. 获取Environment对象,将当前系统属性对象放到Environment中
				5. 准备监听集合对象,默认为null。
			*/
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//创建容器对象DefaultListableBeanFactory
			//完成BeanDefinition的初始化。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			//省略部分代码
		}
	}

prepareRefresh

protected void prepareRefresh() {
		// Switch to active.
		// 设置容器启动时间
		this.startupDate = System.currentTimeMillis();
		// 容器的关闭标志位
		this.closed.set(false);
		// 容器的激活标志位
		this.active.set(true);

		// 记录日志
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		//空方法,方便自定义扩展
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		//验证需要的属性文件是否都已经放入环境中
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		/// 判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到此集合中
		//Spring中applicationListeners为null,但SpringBoot启动时不为null
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		// 创建刷新前的监听事件集合
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

validateRequiredProperties
属性校验,如果走默认方法requiredProperties为0,如果initPropertySources进行了扩展设置了一些属性,则会遍历看getProperty中是否包含该属性,不包含则抛异常。

public void validateRequiredProperties() {
		MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
		
		for (String key : this.requiredProperties) {
			if (this.getProperty(key) == null) {
				ex.addMissingRequiredProperty(key);
			}
		}
		if (!ex.getMissingRequiredProperties().isEmpty()) {
			throw ex;
		}
	}

obtainFreshBeanFactory()

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 刷新beanFactory
		refreshBeanFactory();
		// 获取beanFactory对象
		return getBeanFactory();
	}

refreshBeanFactory

如果存在beanFactory就销毁,并获取新的DefaultListableBeanFactory

protected final void refreshBeanFactory() throws BeansException {
		// 如果存在beanFactory,则销毁关闭beanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建DefaultListableBeanFactory,会在父类AbstractAutowireCapableBeanFactory构造方法中,忽略Aware接口
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 为了序列化指定id,可以从id反序列化到beanFactory对象
			beanFactory.setSerializationId(getId());
			//定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖
			customizeBeanFactory(beanFactory);
			//加载xml文件
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
		}
	}

AbstractAutowireCapableBeanFactory
DefaultListableBeanFactory

public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		this();
		//设置父类工厂
		setParentBeanFactory(parentBeanFactory);
	}
public AbstractAutowireCapableBeanFactory() {
		super();
		// 忽略要依赖的接口
		ignoreDependencyInterface(BeanNameAware.class);
		ignoreDependencyInterface(BeanFactoryAware.class);
		ignoreDependencyInterface(BeanClassLoaderAware.class);
	}
public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		// 如果当前已经有一个父级bean工厂,且传进来的父级bean工厂与当前父级bean工厂不是同一个
		if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
			// 抛出异常
		}
		if (this == parentBeanFactory) {
			throw new IllegalStateException("Cannot set parent bean factory to self");
		}
		this.parentBeanFactory = parentBeanFactory;
	}

customizeBeanFactory
可重写customizeBeanFactory方法来改写allowBeanDefinitionOverriding的值

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		// 如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性,是否允许覆盖同名称的不同定义的对象
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		// 如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性,是否允许bean之间存在循环依赖
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

loadBeanDefinitions

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		// 创建一个XmlBeanDefinitionReader,并通过回调设置到beanFactory中
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		// 给reader对象设置环境对象
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		//目的是读取本地文件库xsd.dtd等文件。
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		//  初始化beanDefinitionReader对象,此处设置配置文件是否要进行验证
		initBeanDefinitionReader(beanDefinitionReader);
		// 开始完成beanDefinition的加载
		loadBeanDefinitions(beanDefinitionReader);
	}

ResourceEntityResolver
首先会在父类DelegatingEntityResolver构造方法中给dtdResolver和schemaResolver属性赋值,其对应属性的作用是,我们正常的xml中,会对xml中标签、标签属性等进行规范和约定,而规范的文件主要就是xsd和dtd文件类型,如果网络不好或者无网,可加载使用本地dtd、xsd文件,其位置就在META-INF/spring.schemas。

public DelegatingEntityResolver(@Nullable ClassLoader classLoader) {
		//BeansDtdResolver中有属性 DTD_EXTENSION = ".dtd"; 和 DTD_NAME = "spring-beans";
		this.dtdResolver = new BeansDtdResolver();
		// 当完成这行代码的调用之后,大家神奇的发现一件事情,schemaResolver对象的schemaMappings属性被完成了赋值操作,但是你遍历完成所有代码后依然没有看到显式调用
		// 其实此时的原理是非常简单的,我们在进行debug的时候,因为在程序运行期间需要显示当前类的所有信息,所以idea会帮助我们调用toString方法,只不过此过程我们识别不到而已
		//PluggableSchemaResolver中有 DEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas";
		this.schemaResolver = new PluggableSchemaResolver(classLoader);
	}

loadBeanDefinitions
getConfigLocations方法获取到之前解析到的xml文件名调用loadBeanDefinitions进行解析。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		// 以Resource的方式获得配置文件的资源位置
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		// 以String的形式获得配置文件的位置,configLocations是根据上一篇解析中获得。
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

loadBeanDefinitions
获取ResourceLoader对象,将String[]的configLocations转换成Resource[]。

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		//此处获取resourceLoader对象
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				// 调用DefaultResourceLoader的getResource完成具体的Resource定位
				//将String[]形式的configLocations转换成Resource[]
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				return count;
			}
			catch (IOException ex) {
				//略。。
			}
		}
		else {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
			int count = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			return count;
		}
	}

loadBeanDefinitions
调用DefaultResourceLoader的loadBeanDefinitions方法来完成最后的解析。

//创建一个EncodedResource
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		//将resource再封装一层为EncodeResource
		return loadBeanDefinitions(new EncodedResource(resource));
	}
	
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}

		// 通过属性来记录已经加载的资源
		//resourcesCurrentlyBeingLoaded属性为ThreadLocal属性修饰
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException( );
		}

		// 从encodedResource中获取已经封装的Resource对象并再次从Resource中获取其中的inputStream
		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			// 逻辑处理的核心步骤
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		catch (IOException ex) {
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

doLoadBeanDefinitions
doLoadDocument方法中会通过DocumentBuilderFactory创建DocumentBuilder对象,通过DucumentBuilder对象解析xml文档。,将解析到的数据封装成Document对象,对象中有节点、父节点、子节点等属性信息。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			// 此处获取xml文件的document对象,这个解析过程是由documentLoader完成的,从String[] -String-Resource[]- resource,最终开始将resource读取成一个document文档,根据文档的节点信息封装成一个个的BeanDefinition对象
			//内部通过DocumentBuilderFactory来获取DocumentBuilder
			Document doc = doLoadDocument(inputSource, resource);
			int count = registerBeanDefinitions(doc, resource);
			return count;
		}
		//省略部分代码....
		catch (Exception ex) {
			throw ex;
		}
	}

registerBeanDefinitions

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		// 对xml的beanDefinition进行解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		// 完成具体的解析过程
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

doRegisterBeanDefinitions

具体解析xml的代码,root就是最外层的根节点< beans>标签

protected void doRegisterBeanDefinitions(Element root) {
		// Any nested  elements will cause recursion in this method. In
		// order to propagate and preserve  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.
		
		//Delegate就是一个解析器。解析各个节点。 
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
		//是否是默认命名空间
		if (this.delegate.isDefaultNamespace(root)) {
			//是否包含profile。
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						//略
					}
					return;
				}
			}
		}
		//空方法。自定义扩展实现(SpringMVC实现)
		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

parseBeanDefinitions
root.getChildNodes获取beans标签的子节点数量进行遍历。在遍历时,也会判断ele元素是否是defaultNamespace,其默认命名空间标签共有< bean >、< alias >、< import>、< beans >,其他在xml中写的等标签都是自定义命名空间,需要在xml的< beans >中额外引入的,默认命名空间标签为Spring自带标签,两者解析方式不同。

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;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

parseDefaultElement
defaultNamespace

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

parseCustomElement

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		// 获取对应的命名空间
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		// 根据命名空间找到对应的NamespaceHandlerspring
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		// 调用自定义的NamespaceHandler进行解析
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

解析xml标签,读取属性值

根据上面的方法,defaultNamespace和自定义属性标签解析方式不同,下面详解< bean >的解析过程。

parseDefaultElement
以下四种都是defaultNamespace的解析方式。以bean为例。

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

processBeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// beanDefinitionHolder是beanDefinition对象的封装类,封装了BeanDefinition,bean的名字和别名,用它来完成向IOC容器的注册
		// 得到这个beanDefinitionHolder就意味着beandefinition是通过BeanDefinitionParserDelegate对xml元素的信息按照spring的bean规则进行
		// 解析得到的
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 向ioc容器注册解析得到的beandefinition的地方
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			// 在beandefinition向ioc容器注册完成之后,发送消息
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

parseBeanDefinitionElement
方法重载,判断< bean >标签中是否有id、name等属性值。

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		// 解析id属性
		String id = ele.getAttribute(ID_ATTRIBUTE);
		// 解析name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		// 如果bean有别名的话,那么将别名分割解析
		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}
		
		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
		}
		//检验name是否唯一
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}

		// 对bean元素的详细解析
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) {
				try {
					// 如果不存在beanname,那么根据spring中提供的命名规则为当前bean生成对应的beanName
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						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.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
				}
				catch (Exception ex) {
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}
		return null;
	}

parseBeanDefinitionElement

public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
		
		this.parseState.push(new BeanEntry(beanName));

		// 解析class属性
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		// 解析parent属性
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			//此时已经获取到class属性和parent属性,拥有这两个属性并封装到BeanDefinition就可以通过反射来实例化Bean了
			// 创建装在bean信息的AbstractBeanDefinition对象,实际的实现是GenericBeanDefinition
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			// 解析bean标签的各种其他属性
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			// 设置description信息
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

			// 解析元数据
			parseMetaElements(ele, bd);
			// 解析lookup-method属性
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			// 解析replaced-method属性
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			// 解析构造函数参数
			parseConstructorArgElements(ele, bd);
			// 解析property子元素
			parsePropertyElements(ele, bd);
			// 解析qualifier子元素
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
		}
		catch (ClassNotFoundException ex) {
		//略
		}
		finally {
			this.parseState.pop();
		}
		return null;
	}

parseConstructorArgElements
解析< constructor-arg >标签。因为可能会有多个constructor-arg标签,所以获取后,要遍历处理

public void parseConstructorArgElements(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, CONSTRUCTOR_ARG_ELEMENT)) {
				parseConstructorArgElement((Element) node, bd);
			}
		}
	}

parseConstructorArgElement
constructor-arg标签中,index、type、name三个属性不共存。

public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		// 获取index属性
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
		// 获取type属性
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
		// 提取name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		if (StringUtils.hasLength(indexAttr)) {
			try {
			//如果设置了index属性,但值 < 0 ,抛异常
				int index = Integer.parseInt(indexAttr);
				if (index < 0) {
					error("'index' cannot be lower than 0", ele);
				}
				else {
					try {
						this.parseState.push(new ConstructorArgumentEntry(index));
						// 解析ele对应的属性元素
						Object value = parsePropertyValue(ele, bd, null);
						ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
						if (StringUtils.hasLength(typeAttr)) {
							valueHolder.setType(typeAttr);
						}
						if (StringUtils.hasLength(nameAttr)) {
							valueHolder.setName(nameAttr);
						}
						valueHolder.setSource(extractSource(ele));
						// 不允许重复指定相同参数
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
							bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
						}
					}
					finally {
						this.parseState.pop();
					}
				}
			}
			catch (NumberFormatException ex) {
				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
			}
		}
		else {
			// 没有index属性则忽略属性,自动寻找
			try {
				this.parseState.push(new ConstructorArgumentEntry());
				Object value = parsePropertyValue(ele, bd, null);
				ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
				if (StringUtils.hasLength(typeAttr)) {
					valueHolder.setType(typeAttr);
				}
				if (StringUtils.hasLength(nameAttr)) {
					valueHolder.setName(nameAttr);
				}
				valueHolder.setSource(extractSource(ele));
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
			}
			finally {
				this.parseState.pop();
			}
		}
	}

parsePropertyValue

public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
		String elementName = (propertyName != null ?
				" element for property '" + propertyName + "'" :
				" element");

		// Should only have one child element: ref, value, list, etc.
		// 一个属性只能对应一种类型:ref、value、list等
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			// 如果匹配到description或者meta不处理
			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;
				}
			}
		}

		// 解析constructor-arg上的ref属性
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		// 解析constructor-arg上的value属性
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null)) {
			/**
			 * 在constructor-arg上不存在:
			 * 		1、既有ref属性又有value属性
			 * 		2、存在ref属性或者value属性且又有子元素
			 */
			error(elementName +
					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}

		if (hasRefAttribute) {
			// ref属性的处理,使用runtimeBeanReference封装对应的ref名称
			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;
		}
		else if (hasValueAttribute) {
			// value属性的处理,使用TypedStringValue封装
			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.
			// 如果既没有ref属性也没有value属性,也没有子元素,那么spring会报错
			error(elementName + " must specify a ref or value", ele);
			return null;
		}
	}

扩展initPropertySources

再次启动,initPropertySources方法就会走我们拓展的方法。

public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {


    public MyClassPathXmlApplicationContext(String... configLocations){
        super(configLocations);
    }

    @Override
    protected void initPropertySources() {
        System.out.println("扩展initPropertySource");
        getEnvironment().setRequiredProperties("abc");
    }
    
	 @Override
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        super.setAllowBeanDefinitionOverriding(false);
        super.setAllowCircularReferences(false);
    }
}

public class Test {
    public static void main(String[] args) {
       ApplicationContext ac1 = new MyClassPathXmlApplicationContext("spring-${username}.xml");
    }
}

你可能感兴趣的:(Spring源码,spring,java)