由於字數超過了限制,因此分紅了三篇,承接上篇:
https://www.jianshu.com/p/a0cfaedf3fc5java
代碼過寬,能夠shift + 鼠標滾輪 左右滑動查看node
先跟蹤一個bean標籤,下面是對應的配置文件spring
<!--配置mapper.java掃描--> <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.mrdear.mapper"/> <property name="properties"> <value> mappers=tk.mybatis.mapper.common.Mapper </value> </property> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean>
由於是bean標籤,走的默認的名稱空間方法,因此走這個標籤的方法:sql
//3.若是該標籤屬於beans的名稱空間,則進入這個方法 //xmlns="http://www.springframework.org/schema/beans" parseDefaultElement(ele, delegate);
這個方法的實如今DefaultBeanDefinitionDocumentReader類中,由於
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 // 若是是嵌套的beans,那麼就會從新調用標記2中的一個方法進行遞歸 doRegisterBeanDefinitions(ele); } } /** * Process the given bean element, parsing the bean definition * and registering it with the registry. * * 處理bean元素,解析成bean definition並註冊到工廠中 */ protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //3.1經過代理解析bean元素 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { //3.2若是有要求的話渲染beanDefinition bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. //3.3註冊最終被渲染的實例到工廠中 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)); } }
跟蹤3.1標記的方法mybatis
進入BeanDefinitionParserDelegate類的parseBeanDefinitionElement方法app
//3.1經過代理解析bean元素 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); /** * Parses the supplied {@code <bean>} element. May return {@code null} * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. * * 解析bean元素。若是解析過程當中發生錯誤則返回空 */ public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { //拿bean標籤上的id String id = ele.getAttribute(ID_ATTRIBUTE); //拿bean標籤上的name屬性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<String>(); //有name屬性進入 if (StringUtils.hasLength(nameAttr)) { //name屬性對應的name值若是有分隔符",; ",那麼切分紅數組 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); //這些name值就是別名 aliases.addAll(Arrays.asList(nameArr)); } //指定了id就用id值做爲bean名稱 String beanName = id; //若是沒有id,可是指定了name,就用name值做爲bean名稱 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { //拿第一個name值做爲bean名稱,其他的仍是別名 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) { //檢查bean名稱和別名是否已經被使用了,若是用了就報錯 //同時把這個bean的名稱和別名加入代理的usedNames屬性中 //private final Set<String> usedNames = new HashSet<String>(); checkNameUniqueness(beanName, aliases, ele); } //直接進入這個方法 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { //既沒有指定id,也沒有指定name就走這裏面 if (!StringUtils.hasText(beanName)) { try { //前面containingBean傳遞時爲null,這裏不走這個方法 if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { //生成一個bean名稱,beanName //若是這個bean是內部bean,全限定名後加#號再加哈希值 //若是是頂層bean,那麼後面加#號再從0開始加數字,id已被註冊數字就增1,直到惟一 //好比:tk.mybatis.spring.mapper.MapperScannerConfigurer#0 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)) { //若是該類名沒有被使用,那麼註冊該類名做爲別名,好比: //tk.mybatis.spring.mapper.MapperScannerConfigurer做爲 //tk.mybatis.spring.mapper.MapperScannerConfigurer#0的別名 aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); //返回beanDefinition的持有者 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; } /** * Parse the bean definition itself, without regard to name or aliases. May return * {@code null} if problems occurred during the parsing of the bean definition. * * 不關注名稱和別名,只解析bean definition自身 */ public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { //解析的時候放入,解析完成彈出,這裏放入bean標籤, //若是還嵌套有子標籤,則後續放入子標籤 //子標籤先彈出 this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { //若是有指定class屬性,則拿到class屬性值 className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { //若是有指定parent屬性,則拿到parent屬性值 parent = ele.getAttribute(PARENT_ATTRIBUTE); } //3.1.1建立BeanDefinition並設置兩屬性 AbstractBeanDefinition bd = createBeanDefinition(className, parent); //3.1.2將bean標籤上的屬性設置到bean definition中 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //若是bean標籤下有子標籤爲description,拿到標籤中的文本,設置到bean definition中 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //若是bean標籤下有子標籤爲meta,拿到他的key和value屬性,設置到bean definition中 parseMetaElements(ele, bd); //若是bean標籤下有子標籤爲lookup-method,拿到他的name和bean屬性,設置到bean definition中 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //若是bean標籤下有子標籤爲replaced-method,設置bean definition parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //若是bean標籤下有子標籤爲constructor-arg,設置bean definition的構造方式 parseConstructorArgElements(ele, bd); //這個標籤比較經常使用,爲Property標籤 //3.1.3解析Property的屬性設置到bean definition中 parsePropertyElements(ele, bd); //有qualifier子標籤才走這個方法 parseQualifierElements(ele, bd); //設置資源 bd.setResource(this.readerContext.getResource()); //這裏爲null 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; }
跟蹤標記3.1.1ide
//3.1.1建立BeanDefinition並設置兩屬性 AbstractBeanDefinition bd = createBeanDefinition(className, parent); /** * Create a bean definition for the given class name and parent name. * * 經過給定的className和parentName建立beanDefinition */ protected AbstractBeanDefinition createBeanDefinition(String className, String parentName) throws ClassNotFoundException { return BeanDefinitionReaderUtils.createBeanDefinition( parentName, className, this.readerContext.getBeanClassLoader()); } /** * 此方法是BeanDefinitionReaderUtils的靜態方法 * * Create a new GenericBeanDefinition for the given parent name and class name, * eagerly loading the bean class if a ClassLoader has been specified. * * 經過給定的parentName和className穿件一個新的GenericBeanDefinition * 若是指定了ClassLoader,就提早加載bean class */ public static AbstractBeanDefinition createBeanDefinition( String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException { GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setParentName(parentName); if (className != null) { if (classLoader != null) { //接受的屬性是Object類型 bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { //接受的屬性是Object類型 bd.setBeanClassName(className); } } return bd; }
跟蹤標記方法3.1.2ui
此方法在BeanDefinitionParserDelegate類中this
//3.1.2將bean標籤上的屬性設置到bean definition中 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); /** * Apply the attributes of the given bean element to the given bean * definition. * * 將bean標籤上的屬性設置到bean definition中 */ public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) { //bean標籤上已經沒有singleton屬性了,用scope代替,因此出現就報錯 if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); } //若是設置了scope就拿其值 else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); } //此處containingBean爲空 else if (containingBean != null) { // Take default from containing bean in case of an inner bean definition. // 若是是一個內部的bean definition,用包含的bean的default bd.setScope(containingBean.getScope()); } //是否有abstract屬性 if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); } String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); //lazyInit若是沒有設置則爲默認值,默認值用的代理類中defaults屬性, //也就是this.defaults if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); //默認值用的代理類中defaults屬性,不進行autowire String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); //默認不進行依賴檢查 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 { //沒有init-method屬性,就拿代理類defaults屬性的 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); bd.setDestroyMethodName(destroyMethodName); } else { //沒有destroy-method屬性,就拿代理類defaults屬性的 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; }
這樣,bean標籤上的屬性也就解析完成了,對其屬性的描述無論設置了仍是沒有設置的,都有相應的值對應到bean definition中。接下來就要解析,bean標籤下的子標籤了。
跟蹤3.1.3標記的方法
此方法在BeanDefinitionParserDelegate類中實現
//3.1.3解析Property的屬性設置到bean definition中 parsePropertyElements(ele, bd); /** * Parse property sub-elements of the given bean element. * 解析bean標籤下property子標籤 */ 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)) { //標籤名爲property才能進入,進入這個方法 parsePropertyElement((Element) node, bd); } } } /** * Parse a property element. */ public void parsePropertyElement(Element ele, BeanDefinition bd) { //拿到property標籤的name屬性 String propertyName = ele.getAttribute(NAME_ATTRIBUTE); if (!StringUtils.hasLength(propertyName)) { error("Tag 'property' must have a 'name' attribute", ele); return; } //解析的時候放入,解析完成彈出,這裏放入property標籤, //這裏面還存有bean父標籤,子標籤解析完成後先彈出 this.parseState.push(new PropertyEntry(propertyName)); try { //bean標籤下能夠有多個property,可是不能重複name屬性 if (bd.getPropertyValues().contains(propertyName)) { error("Multiple 'property' definitions for property '" + propertyName + "'", ele); return; } //進入這個方法,查看是怎麼解析property標籤屬性的 Object val = parsePropertyValue(ele, bd, propertyName); //將name屬性和對應的value放入 PropertyValue pv = new PropertyValue(propertyName, val); //解析property標籤的子標籤meta, //拿到meta的key和value屬性,設置到PropertyValue中 parseMetaElements(ele, pv); //這裏沒有實現,爲null pv.setSource(extractSource(ele)); //將PropertyValue添加到bean definition中 bd.getPropertyValues().addPropertyValue(pv); } finally { //解析的時候放入,解析完成彈出,這裏放入property標籤 this.parseState.pop(); } } /** * Get the value of a property element. May be a list etc. * Also used for constructor arguments, "propertyName" being null in this case. * * 拿到property標籤的value值,多是list * 也被constructor標籤使用,這種狀況propertyName爲null */ public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { //若是propertyName爲null,則是constructor-arg標籤 //不然爲property標籤 String elementName = (propertyName != null) ? "<property> element for property '" + propertyName + "'" : "<constructor-arg> 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); if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) { // Child element is what we're looking for. //除開description和meta標籤,子標籤最多隻能有一個 if (subElement != null) { error(elementName + " must not contain more than one sub-element", ele); } else { subElement = (Element) node; } } } //看標籤屬性用的是value仍是ref boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); //value和ref屬性不能同時存在,若是有子標籤,則value和ref都不能存在,不然報錯 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; } //子標籤不爲null的狀況,進入這個方法查看 else if (subElement != null) { return parsePropertySubElement(subElement, bd); } else { // Neither child element nor "ref" or "value" attribute found. //沒指定ref或者value或者子標籤,返回null error(elementName + " must specify a ref or value", ele); return null; } } /** * 這個方法仍是在BeanDefinitionParserDelegate中 */ public Object parsePropertySubElement(Element ele, BeanDefinition bd) { return parsePropertySubElement(ele, bd, null); } /** * Parse a value, ref or collection sub-element of a property or * constructor-arg element. * * 解析property或者constructor-arg標籤的子標籤,可能爲value, ref或者集合 */ public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) { //若是這個子標籤不屬於beans的名稱空間,則走這個方法 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); } //不然返回null,報錯 else { error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); return null; } } /** * Return a typed String value Object for the given value element. * * 經過指定的value標籤,返回指定的字符串value對象 */ public Object parseValueElement(Element ele, String defaultTypeName) { // It's a literal value. //拿到value中的文本,包括回車、tab製表符、空格 String value = DomUtils.getTextValue(ele); //有無type屬性 String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE); String typeName = specifiedTypeName; if (!StringUtils.hasText(typeName)) { //沒有就用入參defaultTypeName typeName = defaultTypeName; } try { TypedStringValue typedValue = buildTypedStringValue(value, typeName); //這裏設置爲空 typedValue.setSource(extractSource(ele)); //這裏爲空字符串 typedValue.setSpecifiedTypeName(specifiedTypeName); //返回typedValue return typedValue; } catch (ClassNotFoundException ex) { error("Type class [" + typeName + "] not found for <value> element", ele, ex); return value; } }
在生成了BeanDefinitionHolder之後,若是須要的話應該經過代理類對bean definition進行渲染。
跟蹤標記3.2的方法
該方法的實如今BeanDefinitionParserDelegate類中
//3.2若是有要求的話渲染beanDefinition bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) { return decorateBeanDefinitionIfRequired(ele, definitionHolder, null); } public BeanDefinitionHolder decorateBeanDefinitionIfRequired( Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) { BeanDefinitionHolder finalDefinition = definitionHolder; // Decorate based on custom attributes first. // 首先基於自定義屬性進行渲染 // 也就是bean標籤上的屬性,也就是node // 只有當這個node不屬於名稱空間beans纔會進行渲染,這裏就不進去看了 NamedNodeMap attributes = ele.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node node = attributes.item(i); finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } // Decorate based on custom nested elements. // 而後根據標籤內嵌套的子標籤進行渲染 // 這裏是不屬於名稱空間beans的子標籤纔會進行渲染 NodeList children = ele.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } } return finalDefinition; }
最終將完成的bean definition註冊到工廠中
跟蹤標記3.3的方法
//3.3註冊最終被渲染的實例到工廠中 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); /** * Register the given bean definition with the given bean factory. * * 註冊bean definition */ public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. // 3.3.1註冊bean definition的beanName // 好比tk.mybatis.spring.mapper.MapperScannerConfigurer#0 String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. // 若是有別名的話,爲bean name註冊別名 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { //3.3.2註冊別名 registry.registerAlias(beanName, alias); } } }
跟蹤標記3.3.1的方法
// 3.3.1註冊bean definition的beanName registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); @Override 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 { //作一個驗證,靜態工廠方法和覆蓋方法不能組合使用 //若是bean definition中的beanClass屬性不是String類型而是Class類型 //那麼就要驗證和準備這個bean定義的覆蓋方法,檢查指定名稱的方法是否存在 ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition oldBeanDefinition; //查看beanName是否已經被註冊在工廠的beanDefinitionMap屬性中 oldBeanDefinition = this.beanDefinitionMap.get(beanName); //已經被註冊走這個方法,這裏不查看 if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(oldBeanDefinition)) { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else { if (this.logger.isDebugEnabled()) { this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } this.beanDefinitionMap.put(beanName, beanDefinition); } else { //這裏面表明beanName尚未被註冊 //而後根據階段不一樣又有一層判斷 if (hasBeanCreationStarted()) { //這個階段是bean已經開始建立 // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if (this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase // 仍然處於啓動時的註冊階段 // 因此這裏走這個方法 //beanDefinitionMap是工廠的一個屬性,ConcurrentHashMap類型 //他保存全部解析好的bean Definition的名稱和實例的映射 this.beanDefinitionMap.put(beanName, beanDefinition); //beanName也單獨使用了一個ArrayList來保存,方便遍歷 this.beanDefinitionNames.add(beanName); //若是該bean definition是手動註冊的,還要從manualSingletonNames中 //移除bean definition的beanName,還要從manualSingletonNames中是LinkedHashSet this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } //這裏跳過 if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
跟蹤3.3.2方法
//3.3.2註冊別名 registry.registerAlias(beanName, alias); @Override public void registerAlias(String name, String alias) { Assert.hasText(name, "'name' must not be empty"); Assert.hasText(alias, "'alias' must not be empty"); if (alias.equals(name)) { //移除別名中的beanName //aliasMap是ConcurrentHashMap類型,保存別名和beanName的映射 this.aliasMap.remove(alias); } else { String registeredName = this.aliasMap.get(alias); //若是別名對應beanName已經被註冊,則不須要再註冊一次 //別名不容許被覆蓋 if (registeredName != null) { if (registeredName.equals(name)) { // An existing alias - no need to re-register return; } if (!allowAliasOverriding()) { throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'."); } } //再檢查一遍,aliasMap中不能已經存在name和alias checkForAliasCircle(name, alias); //工廠的aliasMap屬性保存別名,那麼alias已被註冊 this.aliasMap.put(alias, name); } }
這樣,spring配置文件中爲bean標籤的解析和加載,也就跟蹤完了。
而後再看下非默認名稱空間的標籤的解析和加載。
由於字數超過了限制,因此分紅了三篇,點擊下篇繼續閱讀
https://www.jianshu.com/p/6e0f6fd1cbbd
beans名稱空間
下,不一樣的標籤有不一樣的子方法,對於<bean>
標籤來講,主要分爲三步:
——————————————————————————————————
——————————————————————————————————