<commit_before>---
layout: post
title: Bean
tags:  [JAVA]
categories: [JAVA]
author: liheng
excerpt: "Bean"
---
## Bean

当将XML转换为Document后, 解析来就是调用registerBeanDefinitions(Document, EncodedResource)提取和注册bean了。


#### DefaultBeanDefinitionDocumentReader

最终执行到DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions(Document, XmlReaderContext)方法,
代码如下:

```
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        this.logger.debug("Loading bean definitions");
        Element root = doc.getDocumentElement();
        this.doRegisterBeanDefinitions(root);
    }
```

接下来,就真正地进入Bean的解析阶段了, 进入doRegisterBeanDefinitions(Element)方法, 代码如下:

```
    protected void doRegisterBeanDefinitions(Element root) {
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
        
        //判断xmlns是否为空或者为"http://www.springframework.org/schema/beans"
        if(this.delegate.isDefaultNamespace(root)) { 
            String profileSpec = root.getAttribute("profile"); //beans属性profile
            if(StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
                if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    return;
                }
            }
        }

        this.preProcessXml(root);
        this.parseBeanDefinitions(root, this.delegate);
        this.postProcessXml(root);
        this.delegate = parent;
    }
```

其中, preProcessXml(Element)和postProcessXml(Element) 都是空方法, 它们的作用可以查看[官网][PrePostProcessXML]。
接下来, 进入parseBeanDefinitions(Element, BeanDefinitionParserDelegate)方法, 代码如下:

```
        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)) {
                        //解析beans下的子元素
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }
```

当遇到<bean/>等默认标签时, 则进入parseDefaultElement(Element, BeanDefinitionParserDelegate)方法, 其源码如下:

```
    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 />标签为例, 来看看processBeanDefinition(Element, BeanDefinitionParserDelegate), 代码如下:

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

    }
```

#### BeanDefinitionParserDelegate
我们先来看看parseBeanDefinitionElement(Element)方法, 代码如下:<commit_msg>spring bean loader<commit_after>---
layout: post
title: Bean
tags:  [JAVA]
categories: [JAVA]
author: liheng
excerpt: "Bean"
---
## Bean

当将XML转换为Document后, 解析来就是调用registerBeanDefinitions(Document, EncodedResource)提取和注册bean了。


#### DefaultBeanDefinitionDocumentReader

最终执行到DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions(Document, XmlReaderContext)方法,
代码如下:

```
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        this.logger.debug("Loading bean definitions");
        Element root = doc.getDocumentElement();
        this.doRegisterBeanDefinitions(root);
    }
```

接下来,就真正地进入Bean的解析阶段了, 进入doRegisterBeanDefinitions(Element)方法, 代码如下:

```
protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
        
    //判断xmlns是否为空或者为"http://www.springframework.org/schema/beans"
    if(this.delegate.isDefaultNamespace(root)) { 
        String profileSpec = root.getAttribute("profile"); //beans属性profile
        if(StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
            if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                return;
            }
        }
    }

    this.preProcessXml(root);
    this.parseBeanDefinitions(root, this.delegate);
    this.postProcessXml(root);
    this.delegate = parent;
}
```

其中, preProcessXml(Element)和postProcessXml(Element) 都是空方法, 它们的作用可以查看[官网][PrePostProcessXML]。
接下来, 进入parseBeanDefinitions(Element, BeanDefinitionParserDelegate)方法, 代码如下:

```
        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);//解析beans下的子元素
                    } else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }
```

当遇到<bean/>等默认标签时, 则进入parseDefaultElement(Element, BeanDefinitionParserDelegate)方法, 其源码如下:

```
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 />标签为例, 来看看processBeanDefinition(Element, BeanDefinitionParserDelegate), 代码如下:

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

    }
```

#### BeanDefinitionParserDelegate
我们先来看看parseBeanDefinitionElement(Element)方法, 代码如下:
{'fraction_non_alphanumeric': 0.10752421157188974, 'fraction_numerical': 0.0007449714427613609, 'mean_word_length': 2.9524043179587833, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4026219', 'n_tokens_mistral': 2368, 'n_tokens_neox': 2285, 'n_words': 339}