spring源碼閱讀(二) Bean加載之默認標籤加載

接着上文的內容,咱們經歷了xml資源文件的校驗/解析/終於要進入到Bean的加載中了。node

上文進行到: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)) {
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }

    }

這裏,加載代理類的一個判斷是不是默認命名空間的標籤,把過程分爲兩個步驟,咱們先來看第一個分支,即默認標籤的解析。緩存

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, "bean")) {
            this.processBeanDefinition(ele, delegate);
        } else if (delegate.nodeNameEquals(ele, "beans")) {
            this.doRegisterBeanDefinitions(ele);
        }

    }

默認的這幾個根標籤的解析,咱們就從最關注的"bean"標籤解析開始吧。即:this.processBeanDefinition(ele, delegate)。架構

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);   // 1 if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); // 2 try {
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry()); // 3
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); // 4
        }

    }

這裏分爲幾個步驟:ide

1: 把ele元素解析爲咱們須要的 BeanDefinitionHolder 對象。函數

2: 判斷子元素中,是否有自定義標籤,若是有調用自定義標籤的處理Handle進行處理,並獲取返回的bdHolderui

3: 將解析到的bdHolder註冊到咱們的配置讀取上下文的註冊表中this

4: 觸發Bean註冊完成的事件通知spa

理完思路,那咱們就從第一個步驟開始,即把ele xml節點翻譯成咱們的BeanDefinition對象。架構設計

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        List<String> aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            aliases.addAll(Arrays.asList(nameArr));
        }

        String beanName = id;
        if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
            beanName = (String)aliases.remove(0);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
            }
        }

        if (containingBean == null) {
            this.checkNameUniqueness(beanName, aliases, ele);
        }

        AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
                try {
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
                    } else {
                        beanName = this.readerContext.generateBeanName(beanDefinition);
                        String beanClassName = beanDefinition.getBeanClassName();
                        if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                            aliases.add(beanClassName);
                        }
                    }

                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
                    }
                } catch (Exception var9) {
                    this.error(var9.getMessage(), ele);
                    return null;
                }
            }

            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        } else {
            return null;
        }
    }

這裏首先獲取AbstractBeanDefinition對象,而後組裝成BeanDefinitionHolder。查看parseBeanDefinitionElement 的代碼

public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
        this.parseState.push(new BeanEntry(beanName));
        String className = null;
        if (ele.hasAttribute("class")) {
            className = ele.getAttribute("class").trim();
        }

        try {
            String parent = null;
            if (ele.hasAttribute("parent")) {
                parent = ele.getAttribute("parent");
            }

            AbstractBeanDefinition bd = this.createBeanDefinition(className, parent); this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
            this.parseMetaElements(ele, bd); this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); this.parseConstructorArgElements(ele, bd); this.parsePropertyElements(ele, bd); this.parseQualifierElements(ele, bd);
            bd.setResource(this.readerContext.getResource());
            bd.setSource(this.extractSource(ele));
            AbstractBeanDefinition var7 = bd;
            return var7;
        } catch (ClassNotFoundException var13) {
            this.error("Bean class [" + className + "] not found", ele, var13);
        } catch (NoClassDefFoundError var14) {
            this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
        } catch (Throwable var15) {
            this.error("Unexpected failure during bean definition parsing", ele, var15);
        } finally {
            this.parseState.pop();
        }

        return null;
    }

看這句createBeanDefinition(className, parent),跟進代碼到BeanDefinitionReaderUtils的createBeanDefinition方法

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) {
                bd.setBeanClass(ClassUtils.forName(className, classLoader));
            } else {
                bd.setBeanClassName(className);
            }
        }

        return bd;
    }

這裏建立的是一個GenericBeanDefinition對象。AbstractBeanDefinition一共有三個子類

GenericBeanDefinition

ChildBeanDefinition

RootBeanDefinition

暫時沒看到Root和Child的應用,咱們這裏就只關注下這個GenericBeanDefinition。className不爲空,classLoader爲空,那麼只設置下BeanCassName屬性。

繼續解析:

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) {
        if (ele.hasAttribute("singleton")) {
            this.error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
        } else if (ele.hasAttribute("scope")) {
            bd.setScope(ele.getAttribute("scope"));
        } else if (containingBean != null) {
            bd.setScope(containingBean.getScope());
        }

        if (ele.hasAttribute("abstract")) {
            bd.setAbstract("true".equals(ele.getAttribute("abstract")));
        }

        String lazyInit = ele.getAttribute("lazy-init");
        if ("default".equals(lazyInit)) {
            lazyInit = this.defaults.getLazyInit();
        }

        bd.setLazyInit("true".equals(lazyInit));
        String autowire = ele.getAttribute("autowire");
        bd.setAutowireMode(this.getAutowireMode(autowire));
        String dependencyCheck = ele.getAttribute("dependency-check");
        bd.setDependencyCheck(this.getDependencyCheck(dependencyCheck));
        String autowireCandidate;
        if (ele.hasAttribute("depends-on")) {
            autowireCandidate = ele.getAttribute("depends-on");
            bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; "));
        }

        autowireCandidate = ele.getAttribute("autowire-candidate");
        String destroyMethodName;
        if (!"".equals(autowireCandidate) && !"default".equals(autowireCandidate)) {
            bd.setAutowireCandidate("true".equals(autowireCandidate));
        } else {
            destroyMethodName = this.defaults.getAutowireCandidates();
            if (destroyMethodName != null) {
                String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName);
                bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
            }
        }

        if (ele.hasAttribute("primary")) {
            bd.setPrimary("true".equals(ele.getAttribute("primary")));
        }

        if (ele.hasAttribute("init-method")) {
            destroyMethodName = ele.getAttribute("init-method");
            if (!"".equals(destroyMethodName)) {
                bd.setInitMethodName(destroyMethodName);
            }
        } else if (this.defaults.getInitMethod() != null) {
            bd.setInitMethodName(this.defaults.getInitMethod());
            bd.setEnforceInitMethod(false);
        }

        if (ele.hasAttribute("destroy-method")) {
            destroyMethodName = ele.getAttribute("destroy-method");
            if (!"".equals(destroyMethodName)) {
                bd.setDestroyMethodName(destroyMethodName);
            }
        } else if (this.defaults.getDestroyMethod() != null) {
            bd.setDestroyMethodName(this.defaults.getDestroyMethod());
            bd.setEnforceDestroyMethod(false);
        }

        if (ele.hasAttribute("factory-method")) {
            bd.setFactoryMethodName(ele.getAttribute("factory-method"));
        }

        if (ele.hasAttribute("factory-bean")) {
            bd.setFactoryBeanName(ele.getAttribute("factory-bean"));
        }

        return bd;
    }

這裏解析各類bd的屬性,並設置到bd對象裏。這些屬性好比init-method / destroy-method / lazy-init 這些咱們常常使用的,還有些不熟悉的,能夠到時候用到的時候查看了解下。

下面解析META元素:

public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
        NodeList nl = ele.getChildNodes();

        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            if (this.isCandidateElement(node) && this.nodeNameEquals(node, "meta")) {
                Element metaElement = (Element)node;
                String key = metaElement.getAttribute("key");
                String value = metaElement.getAttribute("value");
                BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
                attribute.setSource(this.extractSource(metaElement));
                attributeAccessor.addMetadataAttribute(attribute);
            }
        }

    }

遍歷全部meta標籤,建立BeanMetaAttribute屬性,並添加到bd中,這裏向上轉型到了BeanMetadataAttributeAccessor類。這裏仍是很清晰的,接口該作什麼事情,仍是分開的很清楚的。這裏是架構設計裏 接口隔離原則的體現。不一樣接口裏,作的事情是不同的,並不混在一塊兒,這樣當一個部分須要改動的時候,不會影響另外一個部分。個人理解。

繼續:解析lookup-method元素

public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
        NodeList nl = beanEle.getChildNodes();

        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            if (this.isCandidateElement(node) && this.nodeNameEquals(node, "lookup-method")) {
                Element ele = (Element)node;
                String methodName = ele.getAttribute("name");
                String beanRef = ele.getAttribute("bean");
                LookupOverride override = new LookupOverride(methodName, beanRef);
                override.setSource(this.extractSource(ele));
                overrides.addOverride(override);
            }
        }

    }

添加到db的overrides屬性裏了。

解析:replaced-method 根look-method標籤相似再也不贅述

解析: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 (this.isCandidateElement(node) && this.nodeNameEquals(node, "constructor-arg")) {
                this.parseConstructorArgElement((Element)node, bd);
            }
        }

    }

先遍歷元素,而後具體的操做,由parseConstructorArgElement方法來負責

public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
        String indexAttr = ele.getAttribute("index");
        String typeAttr = ele.getAttribute("type");
        String nameAttr = ele.getAttribute("name");
        if (StringUtils.hasLength(indexAttr)) {
            try {
                int index = Integer.parseInt(indexAttr);
                if (index < 0) {
                    this.error("'index' cannot be lower than 0", ele);
                } else {
                    try {
                        this.parseState.push(new ConstructorArgumentEntry(index));
                        Object value = this.parsePropertyValue(ele, bd, (String)null);
                        ValueHolder valueHolder = new ValueHolder(value);
                        if (StringUtils.hasLength(typeAttr)) {
                            valueHolder.setType(typeAttr);
                        }

                        if (StringUtils.hasLength(nameAttr)) {
                            valueHolder.setName(nameAttr);
                        }

                        valueHolder.setSource(this.extractSource(ele));
                        if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
                            this.error("Ambiguous constructor-arg entries for index " + index, ele);
                        } else {
                            bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
                        }
                    } finally {
                        this.parseState.pop();
                    }
                }
            } catch (NumberFormatException var19) {
                this.error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
            }
        } else {
            try {
                this.parseState.push(new ConstructorArgumentEntry());
                Object value = this.parsePropertyValue(ele, bd, (String)null);
                ValueHolder valueHolder = new ValueHolder(value);
                if (StringUtils.hasLength(typeAttr)) {
                    valueHolder.setType(typeAttr);
                }

                if (StringUtils.hasLength(nameAttr)) {
                    valueHolder.setName(nameAttr);
                }

                valueHolder.setSource(this.extractSource(ele));
                bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
            } finally {
                this.parseState.pop();
            }
        }

    }

先獲取index/type/name屬性,而後根據有沒有index屬性類分別處理

若是有index屬性,那麼獲取value,並建立valueHolder最終添加到constructorArgumentValues 中。

來看具體的獲取value的過程

public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
        String elementName = propertyName != null ? "<property> element for property '" + propertyName + "'" : "<constructor-arg> element";
        NodeList nl = ele.getChildNodes();
        Element subElement = null;

        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            if (node instanceof Element && !this.nodeNameEquals(node, "description") && !this.nodeNameEquals(node, "meta")) {
                if (subElement != null) {
                    this.error(elementName + " must not contain more than one sub-element", ele);
                } else {
                    subElement = (Element)node;
                }
            }
        }

        boolean hasRefAttribute = ele.hasAttribute("ref");
        boolean hasValueAttribute = ele.hasAttribute("value");
        if (hasRefAttribute && hasValueAttribute || (hasRefAttribute || hasValueAttribute) && subElement != null) {
            this.error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
        }

        if (hasRefAttribute) {
            String refName = ele.getAttribute("ref");
            if (!StringUtils.hasText(refName)) {
                this.error(elementName + " contains empty 'ref' attribute", ele);
            }

            RuntimeBeanReference ref = new RuntimeBeanReference(refName);
            ref.setSource(this.extractSource(ele));
            return ref;
        } else if (hasValueAttribute) {
            TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute("value"));
            valueHolder.setSource(this.extractSource(ele));
            return valueHolder;
        } else if (subElement != null) {
            return this.parsePropertySubElement(subElement, bd);
        } else {
            this.error(elementName + " must specify a ref or value", ele);
            return null;
        }
    }

獲取value的過程分爲幾個主要部分,根據是ref類型,仍是value類型不一樣,或者是子元素類型,操做不一樣

若是是ref類型,建立RuntimeBeanReference對象;若是是value類型,則封裝爲TypedStringVlue類型。若是是子元素類型,則繼續由parsePropertySubElement處理

public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
        return this.parsePropertySubElement(ele, bd, (String)null);
    }

    public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
        if (!this.isDefaultNamespace((Node)ele)) {
            return this.parseNestedCustomElement(ele, bd);
        } else if (this.nodeNameEquals(ele, "bean")) {
            BeanDefinitionHolder nestedBd = this.parseBeanDefinitionElement(ele, bd);
            if (nestedBd != null) {
                nestedBd = this.decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
            }

            return nestedBd;
        } else if (this.nodeNameEquals(ele, "ref")) {
            String refName = ele.getAttribute("bean");
            boolean toParent = false;
            if (!StringUtils.hasLength(refName)) {
                refName = ele.getAttribute("local");
                if (!StringUtils.hasLength(refName)) {
                    refName = ele.getAttribute("parent");
                    toParent = true;
                    if (!StringUtils.hasLength(refName)) {
                        this.error("'bean', 'local' or 'parent' is required for <ref> element", ele);
                        return null;
                    }
                }
            }

            if (!StringUtils.hasText(refName)) {
                this.error("<ref> element contains empty target attribute", ele);
                return null;
            } else {
                RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
                ref.setSource(this.extractSource(ele));
                return ref;
            }
        } else if (this.nodeNameEquals(ele, "idref")) {
            return this.parseIdRefElement(ele);
        } else if (this.nodeNameEquals(ele, "value")) {
            return this.parseValueElement(ele, defaultValueType);
        } else if (this.nodeNameEquals(ele, "null")) {
            TypedStringValue nullHolder = new TypedStringValue((String)null);
            nullHolder.setSource(this.extractSource(ele));
            return nullHolder;
        } else if (this.nodeNameEquals(ele, "array")) {
            return this.parseArrayElement(ele, bd);
        } else if (this.nodeNameEquals(ele, "list")) {
            return this.parseListElement(ele, bd);
        } else if (this.nodeNameEquals(ele, "set")) {
            return this.parseSetElement(ele, bd);
        } else if (this.nodeNameEquals(ele, "map")) {
            return this.parseMapElement(ele, bd);
        } else if (this.nodeNameEquals(ele, "props")) {
            return this.parsePropsElement(ele);
        } else {
            this.error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
            return null;
        }
    }

這裏能夠看到,全部支持的子類的分類處理都有了,裏邊的具體內容,就感興趣的進去看了。

2019-07-01 15:11繼續:

構造函數元素的解析說完了,咱們繼續主線解析到db中的,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 (this.isCandidateElement(node) && this.nodeNameEquals(node, "property")) {
                this.parsePropertyElement((Element)node, bd);
            }
        }

    }
public void parsePropertyElement(Element ele, BeanDefinition bd) {
        String propertyName = ele.getAttribute("name");
        if (!StringUtils.hasLength(propertyName)) {
            this.error("Tag 'property' must have a 'name' attribute", ele);
        } else {
            this.parseState.push(new PropertyEntry(propertyName));

            try {
                if (!bd.getPropertyValues().contains(propertyName)) {
                    Object val = this.parsePropertyValue(ele, bd, propertyName);
                    PropertyValue pv = new PropertyValue(propertyName, val);
                    this.parseMetaElements(ele, pv);
                    pv.setSource(this.extractSource(ele));
                    bd.getPropertyValues().addPropertyValue(pv);
                    return;
                }

                this.error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
            } finally {
                this.parseState.pop();
            }

        }
    }

這裏,跟構造函數的property元素解析不一樣的是,這裏是構造了PropertyValue對象,並添加到bd的propertyValues裏了。

qualifier元素解析

public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();

        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            if (this.isCandidateElement(node) && this.nodeNameEquals(node, "qualifier")) {
                this.parseQualifierElement((Element)node, bd);
            }
        }

    }
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
        String typeName = ele.getAttribute("type");
        if (!StringUtils.hasLength(typeName)) {
            this.error("Tag 'qualifier' must have a 'type' attribute", ele);
        } else {
            this.parseState.push(new QualifierEntry(typeName));

            try {
                AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
                qualifier.setSource(this.extractSource(ele));
                String value = ele.getAttribute("value");
                if (StringUtils.hasLength(value)) {
                    qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
                }

                NodeList nl = ele.getChildNodes();

                for(int i = 0; i < nl.getLength(); ++i) {
                    Node node = nl.item(i);
                    if (this.isCandidateElement(node) && this.nodeNameEquals(node, "attribute")) {
                        Element attributeEle = (Element)node;
                        String attributeName = attributeEle.getAttribute("key");
                        String attributeValue = attributeEle.getAttribute("value");
                        if (!StringUtils.hasLength(attributeName) || !StringUtils.hasLength(attributeValue)) {
                            this.error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
                            return;
                        }

                        BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
                        attribute.setSource(this.extractSource(attributeEle));
                        qualifier.addMetadataAttribute(attribute);
                    }
                }

                bd.addQualifier(qualifier);
            } finally {
                this.parseState.pop();
            }
        }
    }

構造Qualifier對象,並添加到bd的qualifier屬性中。

到這裏,從ele文檔元素到BeanDefinition對象的解析基本就完成了。

咱們梳理下大體的思路,其實就是解析各類元素,針對不一樣元素或是生成bd的屬性,或是添加到對應的屬性列表中,總之ele要徹底轉換成咱們後續須要使用的BeanDefinition中。

下面,作了這麼多解析工做,咱們來完整的看一下BeanDefinition的屬性

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
    public static final String SCOPE_DEFAULT = "";
    // 省略部分靜態變量及final常量

private String scope = SCOPE_DEFAULT; // bean的做用域範圍,對應bean屬性scope private boolean abstractFlag; // 是不是抽象,對應bean屬性abstract private boolean lazyInit; // 是否延遲加載,對應bean屬性lazy-init private int autowireMode; // 自動注入模式 AUTOWIRE_NO AUTOWIRE_BY_NAME AUTOWIRE_BY_TYPE AUTOWIRE_CONSTRUCTOR private int dependencyCheck; // 依賴檢查,spring3.0後棄用 private String[] dependsOn; // 表示一個bean的實例化依靠另外一個bean先實例化,對應bean的屬性depend-on private boolean autowireCandidate; // autowireCandiate屬性設置爲false,這樣容器在查找自動裝配對象時,將不考慮該bean,即它不會考慮做爲其餘bean自動裝配的候選者,可是該bean自己可使用自動化裝配來注入其餘bean private boolean primary; // 自動裝配時,若是出現多個bean候選者,將做爲首選者,對應baen屬性primary private final Map<String, AutowireCandidateQualifier> qualifiers; // 用於記錄Qualifier,對應子元素qualifier private boolean nonPublicAccessAllowed; // 容許訪問非公開的構造起和方法,程序設置 private boolean lenientConstructorResolution; // 是否以寬鬆模式解析構造函數,默認爲true private ConstructorArgumentValues constructorArgumentValues; // 記錄構造函數注入屬性,對應bean屬性constructor-arg private MutablePropertyValues propertyValues; // 普通屬性集合 private MethodOverrides methodOverrides; // 方法重寫持有者,記錄lookup-method/ replace-method元素 private String factoryBeanName; // 用於bean屬性factoryBean private String factoryMethodName; // 對應bean屬性factory-method private String initMethodName; // 初始化方法,對應bean屬性init-method private String destroyMethodName; // 銷燬方法,對應bean屬性destroy-method private boolean enforceInitMethod; // 是否執行init-method,程序設置 private boolean enforceDestroyMethod; // 是否執行destroy-method,程序設置 private boolean synthetic; // 是不是用戶定義的而不是應用程序自己定義的,建立AOP時候爲true,程序設置 private int role; // 定義bean的應用,APPLICATION:用戶/ INFRASTRUCTURE:徹底內部使用,與用戶無關/ SUPPORT某些複雜配置的一部分,程序設置 private String description; // bean描述信息 private Resource resource; // 這個bean定義的資源

以上有些元素其實沒怎麼使用過,不是太熟悉,這些內容主要參考了《spring源碼深度解析》- 郝佳著

OK,咱們回到以前bean解析的代碼再來繼續:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try {
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

咱們以前重點都是在delegate.parseBeanDefinitionElement 的解析說明上,咱們繼續下邊這句

bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder) ,根據方法的名稱,其實大概能夠判斷意思,若是有必要裝飾BeanDefinition對象

咱們進入代碼來看一下:

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
        return this.decorateBeanDefinitionIfRequired(ele, definitionHolder, (BeanDefinition)null);
    }
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
        BeanDefinitionHolder finalDefinition = definitionHolder;
        NamedNodeMap attributes = ele.getAttributes();

        for(int i = 0; i < attributes.getLength(); ++i) {
            Node node = attributes.item(i);
            finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
        }

        NodeList children = ele.getChildNodes();

        for(int i = 0; i < children.getLength(); ++i) {
            Node node = children.item(i);
            if (node.getNodeType() == 1) {
                finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
            }
        }

        return finalDefinition;
    }

    public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
        String namespaceUri = this.getNamespaceURI(node);
        if (!this.isDefaultNamespace(namespaceUri)) {
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler != null) {
                return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
            }

            if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
                this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
            } else if (this.logger.isDebugEnabled()) {
                this.logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
            }
        }

        return originalDef;
    }

 能夠看到主要動做是,對屬性及子元素進行處理,若是是默認元素,直接掠過,若是不是則根據命名空間,查找對應的處理handler進行解析處理,具體的解析過程暫時先放這裏,後續再說。這裏

只介紹下作了什麼事情。

繼續咱們的核心步驟,該到註冊步驟了,將咱們的beanDefinition註冊到註冊表中。

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            String[] var4 = aliases;
            int var5 = aliases.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String alias = var4[var6];
                registry.registerAlias(beanName, alias);
            }
        }

    }

這裏有兩個部分,一個是根據beanName註冊,一個是根據alias註冊

咱們看第一個根據beanName註冊:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var4) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var4);
            }
        }

        BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (oldBeanDefinition != null) {
            if (!this.allowBeanDefinitionOverriding) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
            }

            if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
                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 (this.logger.isInfoEnabled()) {
                this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
            }
        } else {
            this.beanDefinitionNames.add(beanName);  // 記錄beanName this.manualSingletonNames.remove(beanName);
            this.frozenBeanDefinitionNames = null;
        }

        this.beanDefinitionMap.put(beanName, beanDefinition); if (oldBeanDefinition != null || this.containsSingleton(beanName)) {
            this.resetBeanDefinition(beanName); // 重置全部beanName對應的緩存
        }

    }

這裏還有一個校驗,這裏的校驗主要校驗的是methodOverrides,主要校驗是否有這個類和這個類是否有相應的方法。

這裏的操做:

1:校驗,校驗methodOverrides屬性的正確性和有效性

2:查看是否已經有了該beanName,若是有而後查看是否配置可覆蓋,若是不是,直接拋出異常;若是設置能夠覆蓋,那麼在後續的操做中覆蓋掉便可

3:加入map緩存

4:清除解析前留下的beanName緩存

繼續:經過別名註冊BeanDefinition

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)) {
            this.aliasMap.remove(alias);
        } else {
            if (!this.allowAliasOverriding()) {
                String registeredName = (String)this.aliasMap.get(alias);
                if (registeredName != null && !registeredName.equals(name)) {
                    throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'.");
                }
            }

            this.checkForAliasCircle(name, alias);
            this.aliasMap.put(alias, name);
        }

    }

步驟以下:

1:若是alias名字與name相同,直接刪除原有alias

2:查看是否容許alias覆蓋配置,若是不容許,進行校驗,若是已經註冊的alias的beanName跟當前註冊的beanName不相同,則拋出alias名稱已被註冊到其餘beanName上的異常

3:檢查是否有循環alias

4:註冊alias

至此,默認標籤的解析就梳理完了,後續咱們進行自定義標籤的解析。2019-07-01 17:32分 於圖書館

相關文章
相關標籤/搜索