Spring源碼-IOC容器(二)-Bean的定位解析註冊

Spring IOC容器 源碼解析系列,建議你們按順序閱讀,歡迎討論node

(spring源碼均爲4.1.6.RELEASE版本)spring

  1. Spring源碼-IOC容器(一)-構建簡單IOC容器
  2. Spring源碼-IOC容器(二)-Bean的定位解析註冊
  3. Spring源碼-IOC容器(三)-GetBean
  4. Spring源碼-IOC容器(四)-FactoryBean
  5. Spring源碼-IOC容器(五)-Bean的初始化
  6. Spring源碼-IOC容器(六)-bean的循環依賴
  7. Spring源碼-IOC容器(七)-ApplicationContext
  8. Spring源碼-IOC容器(八)-NamespaceHandler與自定義xml
  9. Spring源碼-IOC容器(九)-Component-Scan源碼解析
  10. Spring源碼-IOC容器(十)-@Autowired解析

Demo

spring中無論是ApplicationContext仍是BeanFactory,要想實現IOC容器,都必須將bean在外部定義的配置信息加載到spring IOC容器中來。而這個處理過程在spring中歸納起來就是:定位、解析和註冊。那麼在spring怎麼才能完成這一操做呢,來看下面的代碼(sample.xml爲spring配置文件,而且放在classpath路徑下)。數據結構

// 1.建立一個ioc配置文件的抽象資源
ClassPathResource resource = new ClassPathResource("sample.xml");
// 2.建立一個BeanFactory實現
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 3.建立一個載入xml文件形式的BeanDefinition讀取器,並將beanFactory經過構造函數傳遞進去
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// 4.讀取資源配置信息,並在XmlBeanDefinitionReader中解析,將解析完的BeanDefinition註冊到beanFactory中
reader.loadBeanDefinitions(resource);

這就是spring加載xml配置文件的核心代碼,也就包括了上面所說的定位解析註冊三大操做。同時能夠看到實例化了一個DefaultListableBeanFactory,由於BeanFactory是IOC容器的基本實現,而DefaultListableBeanFactory實現了BeanFactory,它被用來維護IOC容器中bean的信息和關係。下面就來具體分析spring是如何實現Bean的定位解析和註冊的。mvc

定位

定位,顧名思義,就是找到對應的位置。而在spring中,就是得到資源的輸入流。框架

// 1.建立一個ioc配置文件的抽象資源
ClassPathResource resource = new ClassPathResource("sample.xml");

ClassPathResource實現了Resource接口ide

public interface Resource extends InputStreamSource

Resource接口繼承自org.springframework.core.io.InputStreamSource接口函數

public interface InputStreamSource {
    InputStream getInputStream() throws IOException;
}

於是能夠從ClassPathResource獲取配置文件的輸入流,來看下具體實現post

public InputStream getInputStream() throws IOException {
	InputStream is;
	// 判斷class對象是否爲null,存在就經過getResourceAsStream獲取classpath文件輸入流
	if (this.clazz != null) {
		is = this.clazz.getResourceAsStream(this.path);
	}
	// 判斷class類加載器是否爲null,存在就經過getResourceAsStream獲取classpath文件輸入流
	else if (this.classLoader != null) {
		is = this.classLoader.getResourceAsStream(this.path);
	}
	// 不然就經過系統類加載器(Bootstrap類加載器)獲取classpath文件輸入流
	else {
		is = ClassLoader.getSystemResourceAsStream(this.path);
	}
	if (is == null) {
		throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
	}
	return is;
}

解析

解析指的是將spring的配置文件解析成spring內容存儲的數據結構。這裏的數據結構能夠理解成BeanDefinition。BeanDefinition是spring中的重要接口,它維護了bean的信息在spring內部的映射。ui

/**
 * BeanDefinition用來描述一個bean的定義,
 * 包括bean的屬性、構造函數參數以及
 * 一些具體的信息(單 實例仍是多實例,是否懶加載,依賴beans)。
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 19.03.2004
 * @see ConfigurableListableBeanFactory#getBeanDefinition
 * @see org.springframework.beans.factory.support.RootBeanDefinition
 * @see org.springframework.beans.factory.support.ChildBeanDefinition
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    /**
     * 單實例
     */
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

    /**
     * 多實例
     */
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    /**
     * 父BeanDefinition的name
     */
    String getParentName();

    /**
     * bean的實現的全路徑名稱
     */
    String getBeanClassName();

    /**
     * 工廠bean的名稱
     */
    String getFactoryBeanName();

    /**
     * 工廠方法名稱
     */
    String getFactoryMethodName();

    /**
     * bean的做用域
     */
    String getScope();

    /**
     * 是否懶加載
     */
    boolean isLazyInit();

    /**
     * 依賴的beans
     */
    String[] getDependsOn();

    /**
     * 是否容許被自動裝配
     */
    boolean isAutowireCandidate();

    /**
     * 是否優先自動裝配
     */
    boolean isPrimary();

    /**
     * 構造方法參數值
     */
    ConstructorArgumentValues getConstructorArgumentValues();

    /**
     * 屬性名稱與值
     */
    MutablePropertyValues getPropertyValues();


    /**
     * 是否單實例
     */
    boolean isSingleton();

    /**
     * 是否多實例
     */
    boolean isPrototype();

    /**
     * 是否抽象
     */
    boolean isAbstract();

    /**
     * 角色提示
     */
    int getRole();

    /**
     * 描述
     */
    String getDescription();

    /**
     * 資源描述
     */
    String getResourceDescription();

    /**
     * 返回原始bean,若是沒有返回null
     */
    BeanDefinition getOriginatingBeanDefinition();

}

能夠看到BeanDefinition定義了許多bean的重要信息,好比beanClassName,單例仍是多例,是否懶加載等。在解析以前實例化了兩個對象:this

// 2.建立一個BeanFactory實現
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 3.建立一個載入xml文件形式的BeanDefinition讀取器,並將beanFactory經過構造函數傳遞進去
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);

DefaultListableBeanFactory是BeanFactory的實現,BeanFactory是spring另外一個重要的接口,它定義了從spring獲取實例化後的bean對象的方法。

public interface BeanFactory {

    // 標識一個FactoryBean
    String FACTORY_BEAN_PREFIX = "&";
    
    // 五種獲取bean實例對象的方法
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    
    // 是否存在name的bean
    boolean containsBean(String name);
    
    // bean是否爲單例
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    
    // bean是否爲多例
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    
    // bean是否爲指定的Class類型
    boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
    
    // 獲取bean的Class類型
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    
    // bean的暱稱
    String[] getAliases(String name);

}

來XmlBeanDefinitionReader的構造函數

public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
	super(registry);
}

它的父類是AbstractBeanDefinitionReader

protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
    // 設置BeanDefinitionRegistry,用於註冊Bean
    this.registry = registry;
    
    // 決定要使用的ResourceLoader 
    if (this.registry instanceof ResourceLoader) {
    	this.resourceLoader = (ResourceLoader) this.registry;
    }
    else {
    	this.resourceLoader = new PathMatchingResourcePatternResolver();
    }
    
    // 決定要使用的Environment
    if (this.registry instanceof EnvironmentCapable) {
    	this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
    }
    else {
    	this.environment = new StandardEnvironment();
    }
}

真正的解析從下面開始

reader.loadBeanDefinitions(resource);

調用的是XmlBeanDefinitionReader的loadBeanDefinitions方法

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(new EncodedResource(resource));
}

將Resource封裝成EncodedResource

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    try {
        // 拿到配置文件的輸入流
    	InputStream inputStream = encodedResource.getResource().getInputStream();
    	try {
    	    // 封裝成InputSource,設置編碼
    		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);
    }
}

實際調用的仍是doLoadBeanDefinitions方法

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
	throws BeanDefinitionStoreException {
    try {
        // 解析xml文件得到Document對象
    	Document doc = doLoadDocument(inputSource, resource);
    	// 解析Document爲BeanDefinition並註冊到BeanFactory
    	return registerBeanDefinitions(doc, resource);
    }
}

能夠看到registerBeanDefinitions方法其實綜合瞭解析和註冊兩個功能。先看下解析Document。

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
	return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
			getValidationModeForResource(resource), isNamespaceAware());
}

this.documentLoader實際上是已經實例化的類變量

private DocumentLoader documentLoader = new DefaultDocumentLoader();

來看下loadDocument的實現

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
		ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

	DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
	if (logger.isDebugEnabled()) {
		logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
	}
	DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
	return builder.parse(inputSource);
}

spring默認使用了DOM的解析方式,經過建立DocumentBuilder來解析Document對象。再來看registerBeanDefinitions方法。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	documentReader.setEnvironment(getEnvironment());
	int countBefore = getRegistry().getBeanDefinitionCount();
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	return getRegistry().getBeanDefinitionCount() - countBefore;
}

XmlBeanDefinitionReader將真正的解析過程委託給了BeanDefinitionDocumentReader的實現類DefaultBeanDefinitionDocumentReader。

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	logger.debug("Loading bean definitions");
	Element root = doc.getDocumentElement();
	doRegisterBeanDefinitions(root);
}

從Document拿到根元素,交給doRegisterBeanDefinitions方法

protected void doRegisterBeanDefinitions(Element root) {
    // 獲取父BeanDefinitionParserDelegate
    BeanDefinitionParserDelegate parent = this.delegate;
    // 建立當前BeanDefinitionParserDelegate
    this.delegate = createDelegate(getReaderContext(), root, parent);
    
    //對<beans>的profile屬性進行校驗
    if (this.delegate.isDefaultNamespace(root)) {
    	String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
    	if (StringUtils.hasText(profileSpec)) {
    		String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
    				profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    		if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
    			return;
    		}
    	}
    }
    
    // 解析前擴展點
    preProcessXml(root);
    // 解析根元素
    parseBeanDefinitions(root, this.delegate);
    // 解析後擴展點
    postProcessXml(root);
    
    this.delegate = parent;
}

解析的核心就是對根元素的處理

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // 判斷元素是否爲默認Namespace,即http://www.springframework.org/schema/beans
    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);
    }
}

這個方法決定了對元素的解析是默認的仍是自定義的。spring定義了_http://www.springframework.org/schema/beans_爲默認命名空間,其餘的都是自定義命名空間,包括context,aop,mvc。這種方式讓spring能夠兼容任何其餘擴展,只須要實現NamespaceHandler接口,自定義解析方式。目前其餘框架支持spring配置通常都是經過此種方式實現的。這個之後再專門地進行講解,這裏先來看默認的beans的解析。經過獲取根元素的每一個子節點,交給parseDefaultElement方法處理。

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // import標籤解析
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}
	// alias標籤解析
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}
	// bean標籤解析
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
	// 嵌套的beans標籤解析
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		// recurse
		doRegisterBeanDefinitions(ele);
	}
}

咱們主要關注的是bean標籤的解析

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	// 委託BeanDefinitionParserDelegate解析bean標籤
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		// 對自定義屬性和自定義子節點進行處理
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// 註冊獲得的BeanDefinitionHolder到BeanFactory中
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to register bean definition with name '" +
					bdHolder.getBeanName() + "'", ele, ex);
		}
		// 發送註冊完成事件通知
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

委託BeanDefinitionParserDelegate來解析bean標籤

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
		// id屬性,定義bean的name
		String id = ele.getAttribute(ID_ATTRIBUTE);
		// name屬性,定義bean的暱稱
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<String>();
		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);
			if (logger.isDebugEnabled()) {
				logger.debug("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
		// 解析bean的屬性及字節點
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			// 建立BeanDefinitionHolder保存信息
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

bean的屬性和子節點的解析

public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

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

		try {
			String parent = null;
			// parent屬性解析
			if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
				parent = ele.getAttribute(PARENT_ATTRIBUTE);
			}
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			
			// 其餘屬性的解析
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			// bean的描述信息
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
			// meta信息
			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) {
			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) {

		// singleton屬性,早期使用,被scope取代
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		// scope屬性,默認爲singleton單例
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}
		else if (containingBean != null) {
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
		}

		// abstract屬性,爲true則不會實例化
		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}

		// lazy-init屬性,是否懶加載
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		if (DEFAULT_VALUE.equals(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

		// autowire屬性,這裏並非@Autowired的配置
		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		bd.setAutowireMode(getAutowireMode(autowire));

		// dependency-check屬性
		String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
		bd.setDependencyCheck(getDependencyCheck(dependencyCheck));

		// depends-on屬性
		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
		}

		// autowire-candidate屬性
		String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
		if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
			String candidatePattern = this.defaults.getAutowireCandidates();
			if (candidatePattern != null) {
				String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
				bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
			}
		}
		else {
			bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
		}

		// primary屬性
		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
		}

		// init-method, 實例化後執行
		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			if (!"".equals(initMethodName)) {
				bd.setInitMethodName(initMethodName);
			}
		}
		else {
			if (this.defaults.getInitMethod() != null) {
				bd.setInitMethodName(this.defaults.getInitMethod());
				bd.setEnforceInitMethod(false);
			}
		}

		// destroy-method屬性,對象銷燬前執行
		if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
			String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
			if (!"".equals(destroyMethodName)) {
				bd.setDestroyMethodName(destroyMethodName);
			}
		}
		else {
			if (this.defaults.getDestroyMethod() != null) {
				bd.setDestroyMethodName(this.defaults.getDestroyMethod());
				bd.setEnforceDestroyMethod(false);
			}
		}

		// factory-method屬性,能夠經過工廠方法建立實例
		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
		}
		// factory-bean屬性
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
		}

		return bd;
	}

而後是property標籤的解析

public void parsePropertyElement(Element ele, BeanDefinition bd) {
		// Property的名稱
		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;
			}
			// 解析property的值
			Object val = parsePropertyValue(ele, bd, propertyName);
			// 組裝PropertyValue對象
			PropertyValue pv = new PropertyValue(propertyName, val);
			parseMetaElements(ele, pv);
			pv.setSource(extractSource(ele));
			// 添加到BeanDefinition的PropertyValues集合中
			bd.getPropertyValues().addPropertyValue(pv);
		}
		finally {
			this.parseState.pop();
		}
	}

property的值能夠是value或者ref或者是子節點

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屬性
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		// value屬性
		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);
		}

		if (hasRefAttribute) {
			String refName = ele.getAttribute(REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			// 若是是ref屬性,返回RuntimeBeanReference對象
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(ele));
			return ref;
		}
		else if (hasValueAttribute) {
			// 若是是value屬性,轉化成String
			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;
		}
	}

對於存在子節點的繼續解析

public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
		// 自定義的標籤調用自定義的解析方法
		if (!isDefaultNamespace(ele)) {
			return parseNestedCustomElement(ele, bd);
		}
		// bean標籤
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
			if (nestedBd != null) {
				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
			}
			return nestedBd;
		}
		// ref標籤
		else if (nodeNameEquals(ele, REF_ELEMENT)) {
			// A generic reference to any name of any bean.
			String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
			boolean toParent = false;
			if (!StringUtils.hasLength(refName)) {
				// A reference to the id of another bean in the same XML file.
				refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
				if (!StringUtils.hasLength(refName)) {
					// A reference to the id of another bean in a parent context.
					refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
					toParent = true;
					if (!StringUtils.hasLength(refName)) {
						error("'bean', 'local' or 'parent' is required for <ref> element", ele);
						return null;
					}
				}
			}
			if (!StringUtils.hasText(refName)) {
				error("<ref> element contains empty target attribute", ele);
				return null;
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
			ref.setSource(extractSource(ele));
			return ref;
		}
		// idref標籤
		else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
			return parseIdRefElement(ele);
		}
		// value標籤
		else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
			return parseValueElement(ele, defaultValueType);
		}
		// null標籤
		else if (nodeNameEquals(ele, NULL_ELEMENT)) {
			// It's a distinguished null value. Let's wrap it in a TypedStringValue
			// object in order to preserve the source location.
			TypedStringValue nullHolder = new TypedStringValue(null);
			nullHolder.setSource(extractSource(ele));
			return nullHolder;
		}
		// array標籤
		else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
			return parseArrayElement(ele, bd);
		}
		// list標籤
		else if (nodeNameEquals(ele, LIST_ELEMENT)) {
			return parseListElement(ele, bd);
		}
		// set標籤	
		else if (nodeNameEquals(ele, SET_ELEMENT)) {
			return parseSetElement(ele, bd);
		}
		// map標籤
		else if (nodeNameEquals(ele, MAP_ELEMENT)) {
			return parseMapElement(ele, bd);
		}
		// props標籤
		else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
			return parsePropsElement(ele);
		}
		else {
			error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
			return null;
		}
	}

至此全部xml的解析就完成了,接下來就是Bean Definition的註冊。

註冊

在DefaultBeanDefinitionDocumentReader的processBeanDefinition中,解析完xml後會拿到BeanDefinition信息的持有類BeanDefinitionHolder。

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	// 委託BeanDefinitionParserDelegate解析bean標籤
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		// 對自定義屬性和自定義子節點進行處理
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// 註冊獲得的BeanDefinitionHolder到BeanFactory中
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to register bean definition with name '" +
					bdHolder.getBeanName() + "'", ele, ex);
		}
		// 發送註冊完成事件通知
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

經過BeanDefinitionReaderUtils.registerBeanDefinition註冊到BeanFactory。

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// bean的名稱
		String beanName = definitionHolder.getBeanName();
		// 註冊BeanDefinition到DefaultListableBeanFactory
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// 註冊bean的暱稱
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

這裏的registry其實就是DefaultListableBeanFactory,它實現了BeanDefinitionRegistry接口,並被一直傳遞到這裏。DefaultListableBeanFactory的registerBeanDefinition實現:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;

		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) {
			// 校驗部分省略
		}
		else {
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
			this.frozenBeanDefinitionNames = null;
		}
		// 添加到BeanDefinitionMap
		this.beanDefinitionMap.put(beanName, beanDefinition);

		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

這裏的beanDefinitionMap就是存儲BeanDefinition數據的核心Map.

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

至此spring的xml配置文件通過定位,解析和註冊,映射成爲spring內部的數據結構。上面咱們曾提到spring的BeanFactory核心接口,其中的核心方法就是getBean,spring如何實例化、配置以及組裝Bean對象,以及Bean對象之間的依賴關係是如何注入,請看下一章。

相關文章
相關標籤/搜索