摘要:前言繼續(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); ListupdatedDefinitions = 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
摘要:本文是容器源碼分析系列文章的第一篇文章,將會(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)非常成熟了...
摘要:對(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...
摘要:進(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)...
摘要:入門篇學(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...
摘要:從使用到原理學(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)題列表 -...
閱讀 3100·2021-11-22 13:54
閱讀 848·2021-11-04 16:08
閱讀 4577·2021-10-11 11:09
閱讀 3614·2021-09-22 16:05
閱讀 958·2019-08-30 15:54
閱讀 405·2019-08-30 15:44
閱讀 611·2019-08-30 14:05
閱讀 1030·2019-08-30 12:46