成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring源碼一(容器的基本實(shí)現(xiàn)3)

qylost / 2062人閱讀

摘要:前言繼續(xù)前一章,接下來(lái)解析標(biāo)簽的的屬性信息及的注冊(cè)。不過(guò)只不過(guò)是一個(gè)子類的實(shí)現(xiàn),而大部分屬性都是保存到了中去了。也就是函數(shù)中的代碼的解析了。通過(guò)注冊(cè)對(duì)于的注冊(cè),或許很多人認(rèn)為的方式就是將直接放入中就好了,使用作為。

前言:繼續(xù)前一章,接下來(lái)解析Bean標(biāo)簽的的屬性信息及bean的注冊(cè)。 1. 解析當(dāng)前bean標(biāo)簽的內(nèi)容
當(dāng)我們創(chuàng)建了bean信息的承載實(shí)例之后, 便可以進(jìn)行bean信息的各種屬性的解析了, 首先我們進(jìn)入parseBeanDefinitionAttributes方法,parseBeanDefinitionAttributes方法是對(duì)element所有元素屬性進(jìn)行解析:
/**
 * Apply the attributes of the given bean element to the given bean * definition.
 * @param ele bean declaration element
 * @param beanName bean name
 * @param containingBean containing bean definition
 * @return a bean definition initialized according to the bean element attributes
 */
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
        @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

    if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
        error("Old 1.x "singleton" attribute in use - upgrade to "scope" declaration", ele);
    }
    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());
    }

    if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
        bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    }

    String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
    if (DEFAULT_VALUE.equals(lazyInit)) {
        lazyInit = this.defaults.getLazyInit();
    }
    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

    String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
    bd.setAutowireMode(getAutowireMode(autowire));

    if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
        String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
        bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
    }

    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));
    }

    if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
        bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
    }

    if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
        String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
        bd.setInitMethodName(initMethodName);
    }
    else if (this.defaults.getInitMethod() != null) {
        bd.setInitMethodName(this.defaults.getInitMethod());
        bd.setEnforceInitMethod(false);
    }

    if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
        String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
        bd.setDestroyMethodName(destroyMethodName);
    }
    else if (this.defaults.getDestroyMethod() != null) {
        bd.setDestroyMethodName(this.defaults.getDestroyMethod());
        bd.setEnforceDestroyMethod(false);
    }

    if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
        bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
    }
    if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
        bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
    }

    return bd;
}

通過(guò)以上代碼我們可以發(fā)現(xiàn), 在1.0版本會(huì)有一個(gè)singleton 不過(guò)呢, 這個(gè)很快就被取代掉了, 使用的話會(huì)提示錯(cuò)誤信息, 在新的版本里, 我們使用了scpoe=“singleton” 作為一個(gè)新的使用方式, 我們都知道在spring中,所創(chuàng)建的bean 都被認(rèn)為默認(rèn)認(rèn)為是單例的,并且通過(guò)scope這個(gè)關(guān)鍵字,即scope="singleton"。另外scope還有prototype、request、session、global session作用域。scope="prototype"多例。 scope就是一個(gè)作用域,如果有不太理解的話,可以參照一下:Spring scope作用域詳解。在這里只是看了一下scope標(biāo)簽的解析, 那么肯定還會(huì)有很多的屬性, 我們用或者沒(méi)有用過(guò), 但是就不做講解了, 我們知道spring是如何去做的就好了。

2. 解析bean中的元數(shù)據(jù), meta中的內(nèi)容

例如:


  

通常我們通過(guò)配置文件使用spring的時(shí)候, 我們會(huì)用到meta這個(gè)標(biāo)簽,這個(gè)標(biāo)簽中門會(huì)配置上, key, 和value這兩個(gè)屬性,

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 (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
            Element metaElement = (Element) node;
            String key = metaElement.getAttribute(KEY_ATTRIBUTE);
            String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
            BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
            attribute.setSource(extractSource(metaElement));
            attributeAccessor.addMetadataAttribute(attribute);
        }
    }
}

通過(guò)代碼, 我們可以發(fā)現(xiàn), spring通過(guò)解析得到的Element樹對(duì)象去得到子節(jié)點(diǎn), 然后便利子節(jié)點(diǎn), 并且取得meta元素的key值和value的知值,然后將其存儲(chǔ)在attributeAccessor中。由此推測(cè), 其他的子集標(biāo)簽也會(huì)是通過(guò)這種方式去加載, 并且這也符合我們的預(yù)期。

3. 重提AbstractBeanDefinition屬性
至此我們便完成了對(duì)xml文檔到GenericBenaDefinition的轉(zhuǎn)換, 也就是說(shuō)我們將xml里面所有的配置都保存到了一個(gè)java實(shí)例中去了。不過(guò)GenericBenaDefinition只不過(guò)是一個(gè)子類的實(shí)現(xiàn), 而大部分屬性都是保存到了AbstractBeanDefinition中去了。

當(dāng)打開AbstractBeanDefinition這個(gè)類我們可以發(fā)現(xiàn), 幾乎所有同bean配置的屬性都已經(jīng)在這個(gè)類中進(jìn)行了定義:

public static final String SCOPE_DEFAULT = "";

/**
 * Constant that indicates no autowiring at all.
 * @see #setAutowireMode
 */
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

/**
 * Constant that indicates autowiring bean properties by name.
 * @see #setAutowireMode
 */
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

/**
 * Constant that indicates autowiring bean properties by type.
 * @see #setAutowireMode
 */
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

/**
 * Constant that indicates autowiring a constructor.
 * @see #setAutowireMode
 */
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

/**
 * Constant that indicates determining an appropriate autowire strategy
 * through introspection of the bean class.
 * @see #setAutowireMode
 * @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
 * use annotation-based autowiring for clearer demarcation of autowiring needs.
 */
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

這里就不進(jìn)行一一列舉了。

4.注冊(cè)解析的BeanDefinition

對(duì)于配置文件的解析已經(jīng)完成了,我們得到了整個(gè)配置的內(nèi)容, 接下來(lái)呢Spring做的事就是對(duì)注冊(cè)了。也就是processBeanDeefinition函數(shù)中的registerBeanDefinition(bdHolder, getReaderContext(),getRegistry())代碼的解析了。

/**
 * Register the given bean definition with the given bean factory.
 * @param definitionHolder the bean definition including name and aliases
 * @param registry the bean factory to register with
 * @throws BeanDefinitionStoreException if registration failed
 */
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

從上面的代碼可以看出, 解析的beanDefinition都被注冊(cè)到BeanDefinitionRegistry類型的實(shí)例registry, 而對(duì)于beanDefinition的注冊(cè)分成了兩部分:通過(guò)beanName的注冊(cè)以及通過(guò)別名注冊(cè)。

通過(guò)beanName 注冊(cè)BeanDefinition

對(duì)于beanDefinition的注冊(cè), 或許很多人認(rèn)為的方式就是將beanDefinition直接放入map中就好了, 使用beanName作為key。確實(shí),Spring就是這么做的, 只不過(guò)除此之外, 它還做了點(diǎn)別的事情。
@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 {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }

    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }
        else if (existingDefinition.getRole() < beanDefinition.getRole()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (logger.isInfoEnabled()) {
                logger.info("Overriding user-defined bean definition for bean "" + beanName +
                        "" with a framework-generated bean definition: replacing [" +
                        existingDefinition + "] with [" + beanDefinition + "]");
            }
        }
        else if (!beanDefinition.equals(existingDefinition)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Overriding bean definition for bean "" + beanName +
                        "" with a different definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Overriding bean definition for bean "" + beanName +
                        "" with an equivalent definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        if (hasBeanCreationStarted()) {
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                if (this.manualSingletonNames.contains(beanName)) {
                    Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {
            // Still in startup registration phase
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

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

通過(guò)上面的代碼可以發(fā)現(xiàn), Spring確實(shí)將beanName放到了一個(gè)名字叫做beanDefinitionMap這樣的一個(gè)map之中,這個(gè)map的類型是線程安全的ConcurrentHashMap, 而在這之前,只不過(guò)是做了一些驗(yàn)證。而對(duì)于通過(guò)別名進(jìn)行注冊(cè)的BeanDefinition, 代碼是這樣的:
@Override

public void registerAlias(String name, String alias) {
    Assert.hasText(name, ""name" must not be empty");
    Assert.hasText(alias, ""alias" must not be empty");
    synchronized (this.aliasMap) {
        if (alias.equals(name)) {
            this.aliasMap.remove(alias);
            if (logger.isDebugEnabled()) {
                logger.debug("Alias definition "" + alias + "" ignored since it points to same name");
            }
        }
        else {
            String registeredName = this.aliasMap.get(alias);
            if (registeredName != null) {
                if (registeredName.equals(name)) {
                    // An existing alias - no need to re-register
                    return;
                }
                if (!allowAliasOverriding()) {
                    throw new IllegalStateException("Cannot define alias "" + alias + "" for name "" +
                            name + "": It is already registered for name "" + registeredName + "".");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Overriding alias "" + alias + "" definition for registered name "" +
                            registeredName + "" with new target name "" + name + """);
                }
            }
            checkForAliasCircle(name, alias);
            this.aliasMap.put(alias, name);
            if (logger.isTraceEnabled()) {
                logger.trace("Alias definition "" + alias + "" registered for name "" + name + """);
            }
        }
    }
}

通過(guò)以上的代碼我們可以發(fā)現(xiàn), 在得知是注冊(cè)alias的步驟中, 這里也會(huì)有一個(gè)名字為aliasMap的map用來(lái)存儲(chǔ)注冊(cè)的別名,我這里有個(gè)疑惑, 就是怎么才能通過(guò)別名與原有的beanName進(jìn)行映射呢? 如果都注冊(cè)了, 那么將以哪個(gè)為準(zhǔn)呢? 留給以后再看,留給評(píng)論。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73652.html

相關(guān)文章

  • Spring IOC 容器源碼分析系列文章導(dǎo)讀

    摘要:本文是容器源碼分析系列文章的第一篇文章,將會(huì)著重介紹的一些使用方法和特性,為后續(xù)的源碼分析文章做鋪墊。我們可以通過(guò)這兩個(gè)別名獲取到這個(gè)實(shí)例,比如下面的測(cè)試代碼測(cè)試結(jié)果如下本小節(jié),我們來(lái)了解一下這個(gè)特性。 1. 簡(jiǎn)介 Spring 是一個(gè)輕量級(jí)的企業(yè)級(jí)應(yīng)用開發(fā)框架,于 2004 年由 Rod Johnson 發(fā)布了 1.0 版本。經(jīng)過(guò)十幾年的迭代,現(xiàn)在的 Spring 框架已經(jīng)非常成熟了...

    NSFish 評(píng)論0 收藏0
  • 起來(lái)讀Spring源碼吧(容器初始化

    摘要:對(duì)于開發(fā)者來(lái)說(shuō),無(wú)疑是最常用也是最基礎(chǔ)的框架之一。概念上的東西還是要提一嘴的用容器來(lái)管理。和是容器的兩種表現(xiàn)形式。定義了簡(jiǎn)單容器的基本功能。抽象出一個(gè)資源類來(lái)表示資源調(diào)用了忽略指定接口的自動(dòng)裝配功能委托解析資源。 對(duì)于Java開發(fā)者來(lái)說(shuō),Spring無(wú)疑是最常用也是最基礎(chǔ)的框架之一。(此處省略1w字吹Spring)。相信很多同行跟我一樣,只是停留在會(huì)用的階段,比如用@Component...

    libxd 評(píng)論0 收藏0
  • Spring源碼容器基本實(shí)現(xiàn)2)

    摘要:進(jìn)一步解析其他所有屬性并統(tǒng)一封裝至類型的實(shí)例中。是一個(gè)接口,在中存在三種實(shí)現(xiàn)以及。通過(guò)將配置文件中配置信息轉(zhuǎn)換為容器的內(nèi)部表示,并將這些注冊(cè)到中。容器的就像是配置信息的內(nèi)存數(shù)據(jù)庫(kù),主要是以的形式保存。而代碼的作用就是實(shí)現(xiàn)此功能。 前言:繼續(xù)前一章。 一、porfile 屬性的使用 如果你使用過(guò)SpringBoot, 你一定會(huì)知道porfile配置所帶來(lái)的方便, 通過(guò)配置開發(fā)環(huán)境還是生產(chǎn)...

    yagami 評(píng)論0 收藏0
  • 慕課網(wǎng)_《Spring入門篇》學(xué)習(xí)總結(jié)

    摘要:入門篇學(xué)習(xí)總結(jié)時(shí)間年月日星期三說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。主要的功能是日志記錄,性能統(tǒng)計(jì),安全控制,事務(wù)處理,異常處理等等。 《Spring入門篇》學(xué)習(xí)總結(jié) 時(shí)間:2017年1月18日星期三說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個(gè)人學(xué)習(xí)源碼:https://git...

    Ververica 評(píng)論0 收藏0
  • Java深入-框架技巧

    摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過(guò)的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進(jìn)階面試問(wèn)題列表 -...

    chengtao1633 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<