Spring IOC容器 源碼解析系列,建議你們按順序閱讀,歡迎討論node
(spring源碼均爲4.1.6.RELEASE版本)spring
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對象之間的依賴關係是如何注入,請看下一章。