九零后大叔
技术人的点点滴滴

beanfactory篇-(十一)spring的核心过程一之bean描述信息的注册

回顾:通过前面一个章节的了解,我们大概对spring有了一个感性的认识。XmlBeanFactory这个低配版的spring的整体工作过程分两个核心步骤:一、创建一个XmlBeanFactory对象(创建这个对象的实质是将所有的bean的描述信息注册到一个Map中去);二、通过getBean方法,创建bean对象(实质上是根据一的Map种bean描述信息创建对应的bean对象)。大概有了一个总体的认识之后,我们首先看看第一步,也就是创建一个XmlBeanFactory对象(实际上也就是将所有的bean的描述信息注册到一个Map中去)。


1. spring源码解读先导介绍


注意:1.我们做任何框架的源码解读的时候,一定要注意一点,不要去扣所有的细节,而是要关注他的核心脉络。因为如果总是去扣每一个细节,我们会陷入到无穷的细节代码中去,最后导致自己手撕源码失败。在搞清楚核心框架的脉络之后,我们再去扣细枝末节的技术点。2.我们了解一个框架的工作原理的时候,一定要首先找到这个框架的最小功能集或者说核心功能集,待我们了解原理之后(也可以说是搞清楚框架的核心脉络之后),在去查看它的扩展集功能。

上面我们说过,spring的核心工作过程有两个:1.创建一个spring容器;2.创建好spring容器后,通过spring容器去获取bean对象。对于1创建一个spring容器的核心处理在上一章节我们说过,是把bean描述信息封装成对象放置到一个map中去,而通过spring容器去获取bean对象的核心处理我们在上一章节我们也说过,就是根据bean描述信息来创建bean信息并把bean之间的引用关系处理好。


2. bean描述信息的注册过程

//spring核心过程一:启动一个spring容器
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource 
("applicationContext.xml"));

[1] XmlBeanFactory构造方法,完成初始化一个XmlBeanFactory对象的操作

跳转至XmlBeanFactory类

public XmlBeanFactory(Resource resource) throws BeansException {
    this(resource, null);
}

public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
    super(parentBeanFactory);
    //this.reader是XmlBeanDefinitionReader类,调用loadBeanDefinitions方法,即可完成所有的bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)。此时的applicationcontext.xml文件已经被转换成为一个ClassPathResource对象,这个对象实现了Resource接口。
    this.reader.loadBeanDefinitions(resource);
}

[2] 将有的bean描述信息注册的操作,委托给XmlBeanDefinitionReader类

跳转至XmlBeanDefinitionReader类
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
        logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }

    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<EncodedResource>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        //此时applicationContext.xml文件由Resource对象再次转换成为了InputStream对象。
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            //此时applicationContext.xml文件再次由InputStream对象变成了InputSource对象
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            //调用doLoadBeanDefinitions方法,即可完成所有的bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)。
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally {
            inputStream.close();
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

[3] 将有的bean描述信息注册的操作,委托给DefaultBeanDefinitionDocumentReader类

跳转至DefaultBeanDefinitionDocumentReader类

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();
    //再次将注册bean描述信息到Map的处理委托给本类的doRegisterBeanDefinitions方法
    doRegisterBeanDefinitions(root);
}

protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                return;
            }
        }
    }

    preProcessXml(root);
    //调用parseBeanDefinitions方法,即可完成所有的bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)。
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);

    this.delegate = parent;
}

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        //这个for循环用于完成所有的bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)。
        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)) {
                    //如果是import、alias、bean、beans等默认标签,调用parseDefaultElement方法完成某一个bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)。
                    parseDefaultElement(ele, delegate);
                }
                else {
                    //如果是contex,dubbo,mvc,aop,transation等自定义标签,调用parseCustomElement方法完成某一个bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)。自定义标签的解析,不在本文中描述,且在后面的文章中讲解。
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    //import标签的解析
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    //alias标签的解析
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    //bean标签的解析(bean描述信息注册操作)
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            //调用BeanDefinitionReaderUtils工具类的registerBeanDefinition方法,完成某一个bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        // Send registration event.
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

public static void registerBeanDefinition(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    调用registry类的registerBeanDefinition方法,完成某一个bean描述信息注册的操作(即bean描述信息封装成对象后,放置到Map中去)
    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);
        }
    }
}

[3] 将有的bean描述信息注册的操作,委托给DefaultListableBeanFactory类

跳转至DefaultListableBeanFactory类      

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

    oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    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()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            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 + "]");
            }
        }
        //终于到这关键的一步,每一个applicationContext.xml的bean的描述信息,最终都被封装成为了一个beanDefinition对象,然后放置到了DefaultListableBeanFactory类的一个beanDefinitionMap对象中去。这个对象的定义如下:
        //private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
        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 {
            // 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对象的关键行代码提取出来,我们可以清晰的看到整个spring容器启动(就是创建一个XmlBeanFactory对象)的核心抽象过程。[10]步骤有一个循环处理,用于处理所有的bean描述信息的注册,从代码调用看,循环里面执行的就是[11]-[17]步。而[11]-[17]步骤用于完成每一个bean描述信息的注册过程。

    [1] BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beanFactory"));
    [2] XmlBeanFactory -> XmlBeanFactory -> this.reader.loadBeanDefinitions(resource);
    [3] XmlBeanDefinitionReader -> loadBeanDefinitions -> this.loadBeanDefinitions(new EncodedResource(resource));
    [4] XmlBeanDefinitionReader -> loadBeanDefinitions -> var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    [5] XmlBeanDefinitionReader -> doLoadBeanDefinitions -> int validationMode = this.getValidationModeForResource(resource); 此处是读取xml配置文件的格式,然后校验该格式是否正确,一般有两种格式,一种是DTD,一种是XSD的。
    [6] XmlBeanDefinitionReader -> doLoadBeanDefinitions -> Document doc = this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware()); 此处的意思是将xml文件读取成为一个Document内存对象,该对象就是一个树形结构,里面包含了很多的xml中的节点的对象。
    [7] XmlBeanDefinitionReader -> doLoadBeanDefinitions -> this.registerBeanDefinitions(doc, resource); 
    [8] XmlBeanDefinitionReader -> registerBeanDefinitions -> documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource)); 此处才是真正的开始进行注册Bean的操作的过程了。
    [9] DefaultBeanDefinitionDocumentReader -> registerBeanDefinitions -> Element root = doc.getDocumentElement(); 
    [10] DefaultBeanDefinitionDocumentReader -> registerBeanDefinitions -> this.doRegisterBeanDefinitions(root);
    [11] DefaultBeanDefinitionDocumentReader -> doRegisterBeanDefinitions -> this.parseBeanDefinitions(root, this.delegate); 本调用内部就是进行递归便利的方式来进行注册bean的操作了,因为root对象可以获取下面的所有数据
    [12] DefaultBeanDefinitionDocumentReader -> parseBeanDefinitions -> this.parseDefaultElement(ele, delegate); 注册spring的各种bean信息 
    [13] DefaultBeanDefinitionDocumentReader -> parseBeanDefinitions -> delegate.parseCustomElement(ele); 注册dubbo,aop,transaction,mvc等自定义的各种bean信息
    [14] DefaultBeanDefinitionDocumentReader -> parseDefaultElement -> this.processBeanDefinition(ele, delegate);
    [15] DefaultBeanDefinitionDocumentReader -> processBeanDefinition -> BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
    [16] BeanDefinitionReaderUtils -> registerBeanDefinition -> registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    [17] DefaultListableBeanFactory -> registerBeanDefinition -> this.beanDefinitionMap.put(beanName, beanDefinition); 其实前面的所有的步骤,都是为了将所有的xml配置文件中的bean信息注册到DefaultListableBeanFactory中的beanDefinitionMap对象中去。

总结:new一个beanfactory对象的核心业务处理,实际上就是把所有的bean描述信息封装成beanDefinition对象,然后统一放置到DefaultListableBeanFactory所持有的一个beanDefinitionMap对象中去。那么这么做的意义是什么呢?就是为了调用getBean方法创建bean对象做准备,有了bean描述信息就能将一个bean创建出来了。

更多知识请关注公众号

赞(0) 赏一下
未经允许不得转载:九零后大叔的技术博客 » beanfactory篇-(十一)spring的核心过程一之bean描述信息的注册
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

九零后大叔的技术博客

联系我们联系我们

感谢您的支持

支付宝扫一扫打赏

微信扫一扫打赏