springIOC源码解析(二)

上一篇文章讲到解析XML的parseBeanDefinitions(root, this.delegate)方法,首先看看源码
springIOC源码解析(二)_第1张图片

此处isDefaultNamespace方法是获取namespace为http://www.springframework.org/schema/beans的node,可以看到,这里是循环循环处理节点,咱们来看我标红的那行,
springIOC源码解析(二)_第2张图片
可以看到目前对应schema定义的包括”bean”“alis” “beans” “import” ,处理方法为parseDefaultElement(ele, delegate),因为咱们关注的是spring如何管理bean,因此咱们看下processBeanDefinition(ele, delegate);
springIOC源码解析(二)_第3张图片
这里有两个比较关键的步骤

  1. 调用BeanDefinitionParserDelegate对象完成doc中Element->BeanDefinitionHolder的转换
  2. 注册BeanFactory

咱们先看如何第一步转换的过程,整个方法太长,我帖出关键代码

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        String id = ele.getAttribute(ID_ATTRIBUTE);
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

        List<String> aliases = new ArrayList<String>();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }

        String beanName = id;
        if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
            beanName = aliases.remove(0);
                ......
        }

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

        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        .......
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        .......
    }

这里有两个关键点:

  1. 把bean的信息设置到了AbstractBeanDefinition的对象中,最后返回BeanDefinitionHolder;BeanDefinitionHolder是由beanname+aliasArray+beandefinition组成的一个对象(这个方法中有定义配置文件中的属性对应BeanDefinition中的哪个字段,这个过程比较简单,且代码过长我就不贴出来了)
  2. 通过BeanDefinitionHolder把name和beanName、beandefine绑定在一起

再来看看如何注册BeanFactory,追寻这个方法往下看看是如何进行注册的
springIOC源码解析(二)_第4张图片

进入这个注册方法会发现进入了DefaultListableBeanFactory的registerBeanDefinition方法,这个方法太长,无法把图截全,因此我把代码贴出来,并标注一些关键的逻辑

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 oldBeanDefinition;

        oldBeanDefinition = this.beanDefinitionMap.get(beanName);
        //这里判断bean是否已经注册过
        if (oldBeanDefinition != null) {
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                        "': There is already [" + oldBeanDefinition + "] bound.");
            }
            else 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 (!beanDefinition.equals(oldBeanDefinition)) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding bean definition for bean '" + beanName +
                            "' with a different definition: replacing [" + oldBeanDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName +
                            "' with an equivalent definition: replacing [" + oldBeanDefinition +
                            "] 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<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                //储存bean信息
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

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

这里能看到,BeanFactory的实现类中储存了beanName及beanDefinition,那么beanDefinition中保存的又是什么呢?
首先咱们先看些它的来源,顺着代码往回找发现这里的beanDefinition其实是通过Element(我前面有提到)转换得到的,然后咱们再来看看他的定义,这里我把接口的主要方法贴出来

springIOC源码解析(二)_第5张图片
通过这些方法就能很明显的看到BeanDefinition是用来保存bean的各种信息如:父类名、className、scope、依赖关系等等信息

OK,也就是说spring在解析了配置文件之后主要干了两件事

  1. 把bean的相关信息保存在BeanDefinition中
  2. 把beanName及BeanDefinition保存在BeanFactory中

那咱们接着往下看

Engine engine = (Engine)beanFactory.getBean("engine");

如何通过getBean获取bean对象呢?且看下回分解

你可能感兴趣的:(个人笔记)