摘要:注冊(cè)上篇前言上文說到已經(jīng)加載完畢,此時(shí)到了注冊(cè)的時(shí)候。創(chuàng)建新的子委托,該委托具有對(duì)父委托的引用,用于備份,然后最終將重置回其原始父引用。這種行為模擬了一堆委托,實(shí)際上并不需要委托。下篇中也會(huì)補(bǔ)充一些此文中關(guān)于注冊(cè)的細(xì)節(jié)內(nèi)容。
BeanDefinition注冊(cè)-上篇 前言
上文說到Document已經(jīng)加載完畢,此時(shí)到了Spring注冊(cè)BeanDefinition的時(shí)候。下面就一起來探究下Spring是怎么把Xml文檔注冊(cè)成BeanDefinition的吧。XmlBeanDefinitionReader.registerBeanDefinitions
registerBeanDefinitions方法
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //1. 創(chuàng)建BeanDefinitionDocumentReader BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //2. 設(shè)置documentReader的環(huán)境 documentReader.setEnvironment(getEnvironment()); //3. 查詢之前注冊(cè)的BeanDefinition的個(gè)數(shù) int countBefore = getRegistry().getBeanDefinitionCount(); //4. 開始注冊(cè)BeanDefinition,注意里面創(chuàng)建了一個(gè)Reader上下文 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); //5. 計(jì)算此次注冊(cè)的BeanDefinition的個(gè)數(shù) return getRegistry().getBeanDefinitionCount() - countBefore; }創(chuàng)建BeanDefinitionDocumentReader
使用BeanUtils創(chuàng)建一個(gè)DefaultBeanDefinitionDocumentReader對(duì)象,用于解析成BeanDefinition對(duì)象
private Class> documentReaderClass = DefaultBeanDefinitionDocumentReader.class; //創(chuàng)建一個(gè)BeanDefinitionDocumentReader,此處使用的是DefaultBeanDefinitionDocumentReader protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { //利用反射機(jī)制,調(diào)用DefaultBeanDefinitionDocumentReader的構(gòu)造函數(shù),然后創(chuàng)建一個(gè)實(shí)例返回 return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass)); }createReaderContext(resource)
創(chuàng)建一個(gè)XmlReaderContext設(shè)置了命名空間解析器為DefaultNamespaceHandlerResolver
protected XmlReaderContext createReaderContext(Resource resource) { if (this.namespaceHandlerResolver == null) { this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.namespaceHandlerResolver); } protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader()); }DefaultNamespaceHandlerResolver
用來處理不同的命名空間的解析器,這些映射規(guī)則是配置在META-INF/spring.handlers文件中(見附圖)比如對(duì)于xmlns為http://www.springframework.org/schema/c的命名空間的處理器為org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers"; public DefaultNamespaceHandlerResolver(ClassLoader classLoader) { //設(shè)置類加載器和handlerMapping文件的位置 this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); } public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) { Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null"); this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); this.handlerMappingsLocation = handlerMappingsLocation; }documentReader.registerBeanDefinitions
注冊(cè)beanDefinition
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); //獲取xml的根元素Element root = doc.getDocumentElement(); //注冊(cè)BeanDefinition doRegisterBeanDefinitions(root); } protected void doRegisterBeanDefinitions(Element root) { //獲取 profile 屬性值,我此處并沒有設(shè)置此屬性值,所以使用的是默認(rèn)的 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); //如果有配置profile,則進(jìn)入 if (StringUtils.hasText(profileSpec)) { //將profile放入一個(gè)數(shù)組中 //profile可以配置多個(gè),中間以MULTI_VALUE_ATTRIBUTE_DELIMITERS(,或;)分隔 String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); //判斷環(huán)境是否接受此profile數(shù)組,如果環(huán)境中不允許就直接返回,不再進(jìn)行注冊(cè) //這就是為什么pfofile起作用的原因,和環(huán)境中的prfile不一致的配置,不會(huì)被Spring注冊(cè)到容器中 if (!getEnvironment().acceptsProfiles(specifiedProfiles)) { return; } } // Any nested elements will cause recursion in this method. In // order to propagate and preserve default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. //任何嵌套的 元素都將導(dǎo)致此方法中的遞歸。在為了正確地傳播和保存 缺省-*屬性,跟蹤當(dāng)前(父)委托,它可能為空。創(chuàng)建新的(子)委托,該委托具有對(duì)父委托的引用,用于備份,然后最終將this.delegate重置回其原始(父)引用。這種行為模擬了一堆委托,實(shí)際上并不需要委托。這是直接翻譯的,可能比較書面語。 //口語化的描述是,因?yàn)樵谶f歸解析 中,為了正確的保持BeanDefinitionParserDelegate的引用關(guān)系,所以首先取出DefaultBeanDefinitionDocumentReader委托類暫存起來,然后創(chuàng)建一個(gè)新的委托類使用,最后再還原為之前的委托類。 //獲取此DefaultBeanDefinitionDocumentReader的解析委托類 BeanDefinitionParserDelegate parent = this.delegate; //利用現(xiàn)有的委托類(可能為null),創(chuàng)建一個(gè)新的委托類 this.delegate = createDelegate(this.readerContext, root, parent); //預(yù)處理root,當(dāng)前是空實(shí)現(xiàn),可自行擴(kuò)展 preProcessXml(root); //真正的處理root,并注冊(cè),詳細(xì)的見下一小節(jié)《parseBeanDefinitions》 parseBeanDefinitions(root, this.delegate); //后處理root,當(dāng)前是空實(shí)現(xiàn),可自行擴(kuò)展 postProcessXml(root); this.delegate = parent; } //輔助方法分析 //創(chuàng)建一個(gè)新的委托類BeanDefinitionParserDelegate // protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) { //目前createHelper返回的值都是null BeanDefinitionParserDelegate delegate = createHelper(readerContext, root, parentDelegate); //目前都會(huì)進(jìn)入此判斷內(nèi) if (delegate == null) { //創(chuàng)建一個(gè)新的BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext, getEnvironment()); //初始化,并通過readerContext分發(fā)一個(gè)開始注冊(cè)BeanDefinition的事件 delegate.initDefaults(root, parentDelegate); } return delegate; } //BeanDefinitionParserDelegate.initDefaults //默認(rèn)的文檔BeanDefinition private final DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition(); public void initDefaults(Element root, BeanDefinitionParserDelegate parent) { //給defaults設(shè)置初始值 populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root); //分發(fā)一個(gè)defaultsRegistered事件 this.readerContext.fireDefaultsRegistered(this.defaults); } //讀取 中配置的屬性,并設(shè)置到defaults中 protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) { //設(shè)置 default-lazy-init , //值為default時(shí),如果父節(jié)點(diǎn)不是null時(shí),繼承父節(jié)的屬性值,否則為false String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE; } defaults.setLazyInit(lazyInit); //設(shè)置 default-merge //值為default時(shí),如果父節(jié)點(diǎn)不是null時(shí),繼承父節(jié)的屬性值,否則為false String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE); if (DEFAULT_VALUE.equals(merge)) { merge = parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE; } defaults.setMerge(merge); //設(shè)置 default-autowire //值為default時(shí),如果父節(jié)點(diǎn)不是null時(shí),繼承父節(jié)的屬性值,否則為no String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE); if (DEFAULT_VALUE.equals(autowire)) { autowire = parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE; } defaults.setAutowire(autowire); // don"t fall back to parentDefaults for dependency-check as it"s no // longer supported in as of 3.0. Therefore, no nested // would ever need to fall back to it. //設(shè)置 default-dependency-check ,不用檢查父節(jié)點(diǎn)的值了 defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE)); //設(shè)置 default-autowire-candidates if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) { defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates()); } //設(shè)置 default-init-method if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) { defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setInitMethod(parentDefaults.getInitMethod()); } //設(shè)置 default-destroy-method if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) { defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setDestroyMethod(parentDefaults.getDestroyMethod()); } //設(shè)置此DocumentDefaultsDefinition的元數(shù)據(jù)源 defaults.setSource(this.readerContext.extractSource(root)); }
一個(gè)beans的圖示
parseBeanDefinitions委托模式石錘了!這里把root交給委托類delegate來處理,委托類delegate通過XmlReaderContext持有當(dāng)前的XmlBeanDefinitionReader、命名空間解析器、原始資源、事件分發(fā)器等,又直接持有環(huán)境的引用,而XmlBeanDefinitionReader又有BeanDefinitionRegistry的引用,可以說集萬千寵愛于一身,所以能力非常強(qiáng)大。我不得不畫個(gè)圖來表示一下敬意!
這里解析是的
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { //判斷root的xlmns是不是默認(rèn)的名稱空間,即"http://www.springframework.org/schema/beans" //這里是的 if (delegate.isDefaultNamespace(root)) { //獲取全部子節(jié)點(diǎn)并遍歷 NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); //如果節(jié)點(diǎn)是Element的話,這里主要是為了去除xml中無用的Text空節(jié)點(diǎn) //比如:__a____ 是有5個(gè)Node的 //分別是: //1. 空白Text節(jié)點(diǎn) //2. 節(jié)點(diǎn) //3. 空白Text節(jié)點(diǎn) //4. 節(jié)點(diǎn) //5. 空白Text節(jié)點(diǎn) if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { //解析有效節(jié)點(diǎn),處理不同的標(biāo)簽 import bean alias beans parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }parseDefaultElement
處理import 、alias、bean、beans 這四種標(biāo)簽其中最復(fù)雜的就是 beans 標(biāo)簽,他會(huì)導(dǎo)致程序遞歸到DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions方法,然后重復(fù)上面的所有步驟,有興趣的同學(xué)可以在< beans> 標(biāo)簽中嵌入一個(gè)< beans>,來研究下Spring是如何處理遞歸的。我這里就不再深入討論了。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { //處理 import 標(biāo)簽 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } // //處理 alias 標(biāo)簽 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } //處理 bean 標(biāo)簽 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } //處理 beans 標(biāo)簽 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }processBeanDefinition
處理bean標(biāo)簽,先解析默認(rèn)命名空間中的屬性、和子標(biāo)簽然后處理非默認(rèn)命名空間的標(biāo)簽
接著注冊(cè)BeanDefinition
最后發(fā)送一個(gè)BeanDefinition注冊(cè)事件
/** * Process the given bean element, parsing the bean definition * and registering it with the registry. */ protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //解析ele成BeanDefinition,并放入到BeanDefinitionHolder中 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //如果bdHolder解析成功了就進(jìn)行 if (bdHolder != null) { //解析非默認(rèn)命名空間的屬性 //比如 http://www.springframework.org/schema/c 之類的標(biāo)簽 //對(duì)應(yīng)的解析器也是就在springs.handlers文件中配置的,比如*/c的是org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { //向IOC中注冊(cè)該BeanDefiniton!!! BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name "" + bdHolder.getBeanName() + """, ele, ex); } //最后發(fā)送一個(gè)BeanDefinition注冊(cè)事件 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
//調(diào)用parseBeanDefinitionElement public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } //實(shí)際將Element解析成Beanfinition的方法 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { //獲取id屬性 String id = ele.getAttribute(ID_ATTRIBUTE); //獲取name屬性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); //別名list Listaliases = new ArrayList (); //如果name屬性值不為空,按照 ,; 符號(hào)切分name,切分成一個(gè)name屬性,并放入到aliases中 //這里看出bean的定義,可以定義多個(gè)name值,只要通過逗號(hào)或者分號(hào)分隔即可。 if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } //把beanName設(shè)置成id, String beanName = id; //如果沒有配置id,就把name中配置的第一個(gè)值作為beanName 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"); } } //如果傳入的containingBean為null,就檢驗(yàn)beanName和aliases是不是已經(jīng)被占用了, //占用了就拋出一個(gè)異常BeanDefinitionParsingException, //這里傳入的containingBean就是null,所以一定要經(jīng)過里面檢查 if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } //把ele解析 beanDefinition, //其中此處的 beanDefinition的類型是GenericBeanDefinition AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { //如果beanName沒有的話,就使用BeanDefinitionReaderUtils.generateBeanName生成一個(gè)名字 if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { 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)) { 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); // 用一個(gè)BeanDefinitionHolder ,把beanDefinition, beanName, aliasesArray封裝在一起然后返回 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
//檢查benaName、aliases是否被之前的bean占用 protected void checkNameUniqueness(String beanName, Listaliases, Element beanElement) { String foundName = null; //判斷beanName是否被使用 if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) { foundName = beanName; } //判斷是否aliases中有被占用的 if (foundName == null) { foundName = (String) CollectionUtils.findFirstMatch(this.usedNames, aliases); } //如果找到了占用,就拋出異常 if (foundName != null) { error("Bean name "" + foundName + "" is already used in this element", beanElement); } //如果沒有發(fā)現(xiàn)占用,就把beanName和aliaes全部放入到usedNames中 this.usedNames.add(beanName); this.usedNames.addAll(aliases); }
解析Bean中幾乎所有的屬性和一些配置的子標(biāo)簽,一個(gè)示例Bean標(biāo)簽的配置如圖
//Element解析成AbstractBeanDefinition public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { //把beanName壓入到棧parseState中 this.parseState.push(new BeanEntry(beanName)); String className = null; //獲取class屬性值,放入到className中 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { //如果有parent屬性,設(shè)置到parent中 String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } //創(chuàng)建一個(gè)AbstractBeanDefinition,類型是GenericBeanDefinition AbstractBeanDefinition bd = createBeanDefinition(className, parent); //解析ele的屬性,并設(shè)置到BeanDefinition中 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //如果此bean標(biāo)簽有子標(biāo)簽description的話,就把description中的值設(shè)置到bd中 //message bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //解析子標(biāo)簽 // parseMetaElements(ele, bd); //解析子標(biāo)簽,把配置的lookup-method放入到bd的methodOverrides中 // parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //解析 replaced-method 標(biāo)簽 // parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //解析 構(gòu)造函數(shù)標(biāo)簽 // parseConstructorArgElements(ele, bd); //解析 屬性標(biāo)簽 parsePropertyElements(ele, bd); //解析 標(biāo)簽 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; }
//利用className和parentName創(chuàng)建一個(gè)BeanDefinition protected AbstractBeanDefinition createBeanDefinition(String className, String parentName) throws ClassNotFoundException { return BeanDefinitionReaderUtils.createBeanDefinition( parentName, className, this.readerContext.getBeanClassLoader()); } //BeanDefinitionReaderUtils.createBeanDefinition方法創(chuàng)建的BeanDefinition的類型是GenericBeanDefinition public static AbstractBeanDefinition createBeanDefinition( String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException { //創(chuàng)建一個(gè)GenericBeanDefinition,設(shè)置ParentName, GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setParentName(parentName); //如果可以className和classLoader都有值的話,就把類Class加載出來,并設(shè)置到bd中 //如果classLoder為空的話,就只設(shè)置一個(gè)className if (className != null) { if (classLoader != null) { // bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { bd.setBeanClassName(className); } } return bd; }
幾乎設(shè)置了一個(gè)BeanDefinition需要的全部屬性
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) { //解析spring2.x中的scope屬性 //解析Spring1.x中的singleton屬性 if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { // Spring 2.x "scope" attribute bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Specify either "scope" or "singleton", not both", ele); } } else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { // Spring 1.x "singleton" attribute bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ? BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE); } else if (containingBean != null) { // Take default from containing bean in case of an inner bean definition. bd.setScope(containingBean.getScope()); } //設(shè)置bd的 abstract 屬性 if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); } //設(shè)置bd的 lazy-init 屬性 String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); //設(shè)置bd的 autowire 屬性 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); //設(shè)置bd的 dependency-check 屬性 String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE); bd.setDependencyCheck(getDependencyCheck(dependencyCheck)); //設(shè)置bd的 depends-on 屬性 if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); } //設(shè)置bd的 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)); } //設(shè)置bd的 primary 屬性 if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); } //設(shè)置bd的 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); } } //設(shè)置bd的 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); } } //設(shè)置bd的 factory-method 屬性 if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); } //設(shè)置bd的 factory-bean 屬性 if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); } return bd; }
BeanDefinition的繼承關(guān)系圖,可以看出GenericBeanDefinition的位置
寫的有點(diǎn)太多了,還有import標(biāo)簽和 alias標(biāo)簽的解析內(nèi)容,我放置《BeanDefinition注冊(cè)-下篇》中一起講解。下篇中也會(huì)補(bǔ)充一些此文中關(guān)于注冊(cè)BeanDefintion的細(xì)節(jié)內(nèi)容。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/75344.html
摘要:在上文中,我實(shí)現(xiàn)了一個(gè)很簡(jiǎn)單的和容器。比如,我們所熟悉的就是在這里將切面邏輯織入相關(guān)中的。初始化的工作算是結(jié)束了,此時(shí)處于就緒狀態(tài),等待外部程序的調(diào)用。其中動(dòng)態(tài)代理只能代理實(shí)現(xiàn)了接口的對(duì)象,而動(dòng)態(tài)代理則無此限制。 1. 背景 本文承接上文,來繼續(xù)說說 IOC 和 AOP 的仿寫。在上文中,我實(shí)現(xiàn)了一個(gè)很簡(jiǎn)單的 IOC 和 AOP 容器。上文實(shí)現(xiàn)的 IOC 和 AOP 功能很單一,且 I...
Spring是一個(gè)開源的設(shè)計(jì)層面框架,解決了業(yè)務(wù)邏輯層和其他各層的松耦合問題,將面向接口的編程思想貫穿整個(gè)系統(tǒng)應(yīng)用,同時(shí)它也是Java工作中必備技能之一... 前言 緊跟上篇 Spring解密 - XML解析 與 Bean注冊(cè) ,我們接著往下分析源碼 解密 在 Spring 的 XML 配置里面有兩大類聲明,一個(gè)是默認(rèn)的如 ,另一類就是自定義的如,兩種標(biāo)簽的解析方式差異是非常大的。parseBe...
摘要:使用這個(gè)類庫(kù)中的類將會(huì)加載必要的工廠類和類。最終它并不會(huì)依賴于或來構(gòu)建應(yīng)用程序代碼。下面對(duì)各部分作用總結(jié)下。和無縫整合的機(jī)制和的認(rèn)識(shí)在講如何無縫整合進(jìn)之前,我們先認(rèn)識(shí)下和這兩個(gè)接口的作用。附上上篇博文地址原理概括。 前言 本篇是繼上篇MyBatis原理概括延伸的,所以如果有小伙伴還沒看上篇博文的話,可以先去看下,也不會(huì)浪費(fèi)大家太多的時(shí)間,因?yàn)楸酒獣?huì)結(jié)合到上篇敘述的相關(guān)內(nèi)容。 好,切入正...
摘要:主要過程為調(diào)用自身的另一個(gè)有參構(gòu)造器此處的即為本身此處的最終返回一個(gè)調(diào)用無參構(gòu)造器創(chuàng)建出來的對(duì)象參數(shù)非空效驗(yàn)保存創(chuàng)建一個(gè)用于注解解析器,后面會(huì)用到注冊(cè)需要用到的顧名思義,即為所處的環(huán)境,包括配置的讀取等。 零 前期準(zhǔn)備 0 FBI WARNING 文章異常啰嗦且繞彎。 1 版本 spring版本 : spring 5.1.2.RELEASE IDE : idea 2018.3 2 Be...
摘要:在介紹自定義標(biāo)簽解析前,先放一張圖幫助大家理解以下是如何從文件中解析并加載的。自定義標(biāo)簽比如的值為根據(jù)獲取到的,獲取對(duì)應(yīng)的對(duì)象。關(guān)于和加載先后順序的問題最后再集合一個(gè)小例子總結(jié)下吧當(dāng)我們先解析了元素時(shí),我們會(huì)遍歷所有已經(jīng)注冊(cè)注冊(cè)表中。 今天我們來談?wù)?Dubbo XML 配置相關(guān)內(nèi)容。關(guān)于這部分內(nèi)容我打算分為以下幾個(gè)部分進(jìn)行介紹: Dubbo XML Spring 自定義 XML 標(biāo)...
閱讀 2856·2021-10-14 09:42
閱讀 3173·2019-08-30 15:52
閱讀 3238·2019-08-30 14:02
閱讀 1102·2019-08-29 15:42
閱讀 529·2019-08-29 13:20
閱讀 1156·2019-08-29 12:24
閱讀 469·2019-08-26 10:20
閱讀 680·2019-08-23 18:31