Spring源码之旅(3)_BeanDefinition的解析与注册

Spring源码之旅(3)_BeanDefinition的解析与注册

 

一、 BeanDefinition

spring可以通过xml配置文件定义bean,beanFactory可以创建、查找配置文件中定义的这些beanspring内部是如何将配置文件中所定义的bean变成可以让beanFactory创建与管理的呢?这是依靠BeanDefinition进行实现。BeanDefinition是一个接口,它描述了一个bean的实例,保存了bean的定义信息,是bean在内存中的描述形式。xml配置文件所定义的每个bean在内存中都有对应的Bedifinition对象进行描述。BeanFactory在查找,创建及管理bean时,会先查找其在内存中所保存的BeanDefinition,然后再根据BeanDefinition中的bean描述内容创建bean或返回所需的bean信息。

       根据面向接口编程的原则,spring定义了接口BeanDefinitionRegistry注册管理所有的Bedifinition,实现此接口就可以管理bean的定义,DefaultListableBeanFactory类实现了此接口,因此DefaultListableBeanFactory类及其子类具有管理beanDefinition的功能。

       Spring读取分析配置文件,根据配置文件中的定义,为这些bean创建对应的BeanDifinition,并将BeanDifinition注册至beanFactory(具体表现为注册在DefaultListableBeanFactory类型的beanFactory)。当用户需要使用bean时,将传入bean的名称或类型给beanFactorybeanFactory从其所保存的beanDefinition中查找,当找到符合条件的beanDefinition后,则将根据beanDefinition中的bean信息创建bean对象,并返回给用户。

 

二、 BeanDefinition解析注册序列图

 

三、 实现源码分析

3.1                 beanDefinition加载入口

AbstractRefreshableApplicationContext类在刷新beanFacotry时方法refreshBeanFactory()内部有调用loadBeanDefinitions(beanFactory)方法加载beanDefinition,不过在此类中loadBeanDefinitions还只是抽象方法,其真正在子类AbstractXmlApplicationContext中进行实现。

 

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {

       // 创建XmlBeanDefinitionReader对象,用于读取配置文件中的BeanDefinition

       XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

       // Configure the bean definition reader with this context's

       // resource loading environment.

       beanDefinitionReader.setResourceLoader(this);

       beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

       // 模板方法,空实现

       initBeanDefinitionReader(beanDefinitionReader);

        // 利用beanDefinitionReader加载BeanDefinition信息

       loadBeanDefinitions(beanDefinitionReader);

    }

 

3.2                 XmlBeanDefinitionReader

 

XmlBeanDefinitionReader类用于从资源中加载BeanDefinition, AbstractBeanDefinitionReaderBeanDefinitionReader接口进行了默认实现,除了

int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;

方法。

 

XmlBeanDefinitionReader继承对AbstractXmlBeanDefinitionReader类未实现的方法进行了实现,并在其内部调用了doLoadBeanDefinitions(InputSource inputSource, Resource resource)加载BeanDefinition

//获取resource的验证模式<br/>

int validationMode = getValidationModeForResource(resource);

//创建documentLoader创建xmlDocument对象

Document doc = this.documentLoader.loadDocument(

    inputSource, getEntityResolver(), this.errorHandler, validationMode, this.namespaceAware);

return registerBeanDefinitions(doc, resource);

在此方法内部利用documentLoader(默认为DefaultDocumentLoader)获取xml配置文件的Document对象,然后调用registerBeanDefinitions(doc, resource)方法。

registerBeanDefinitions(doc, resource)方法:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {

       ……………..

       // Read document based on new BeanDefinitionDocumentReader SPI.

       BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();

       //获取解析之前beanFactory中所拥有的beanDefinition数量

       int countBefore = getBeanFactory().getBeanDefinitionCount();

       documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

       //返回从此document中所加载的beanDefintion数量

       return getBeanFactory().getBeanDefinitionCount() - countBefore;

    }

BeanDefinitionDocumentReader 默认使用的DefaultBeanDefinitionDocumentReader类,注册和解析beanDefinition进入DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions方法。

 

3.3               DefaultBeanDefinitionDocumentReader

 

DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions方法:

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {

       this.readerContext = readerContext;

       logger.debug("Loading bean definitions");

       Element root = doc.getDocumentElement();

       BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);

       //模板方法,空实现

       preProcessXml(root);

       //从根节点root解析beanDefinitions

       parseBeanDefinitions(root, delegate);

       //模板方法,空实现

       postProcessXml(root);   

}

首先查看createHelper方法:

protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {

        //创建并最终返回BeanDefinitionParserDelegate对象

       BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);

       //初始化根节点<beans>的属性值,并作为<beans>节点下各bean相关属性的默认配置值

       delegate.initDefaults(root);

       return delegate;

    }

DefaultBeanDefinitionDocumentReader类有一个defaults属性,它是DocumentDefaultsDefinition类型,其内部保存了<beans>元素的一些属性值,将作为<beans>下面的<bean>子节点值的默认配置。

parseBeanDefinitions(root, delegate)方法在其内部调用了

parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)

方法:

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {

       //解析import

       if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {

           importBeanDefinitionResource(ele);

       }

       //解析alias

       else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {

           processAliasRegistration(ele);

       }

       //解析bean

       else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {

           processBeanDefinition(ele, delegate);

       }

    }

在此方法中,对<beans>节点下面的<import><alias>,<bean>子节点进行了解析

importBeanDefinitionResource(ele)方法对import所导入的xml文件,进行递归地解析

processAliasRegistration(ele)则对别名进行了注册

processBeanDefinition方法对bean进行了解析,实现为:

BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

       if (bdHolder != null) {

           bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

           try {

              //注册beanDefinition

              // Register the final decorated instance.

              BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

           }…………..

调用了BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法将<bean>节点解析成了BeanDefinitionHolder对象,然后再将BeanDefinitionHolder里面的beanDifinition注册到了beanFactory

 

3.4               BeanDefinitionParserDelegate

BeanDefinitionParserDelegate类最终调用了方法

AbstractBeanDefinition parseBeanDefinitionElement(

           Element ele, String beanName, BeanDefinition containingBean)

用来解析<bean>节点:

              ……..设置bean的属性

//处理解析<bean>下面的各子标签

           //<meta>子标签

           parseMetaElements(ele, bd);

           //<lookup-method>子标签

           parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

           //<replaced-method>子标签

           parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

           //<constructor-arg>子标签

           parseConstructorArgElements(ele, bd);

           //<property>子标签

           parsePropertyElements(ele, bd);

    bd.setResourceDescription(this.readerContext.getResource().getDescription());

           bd.setSource(extractSource(ele));

           return bd;

在此方法内部实现了解析bean节点及其下的所有子标签,并返回AbstractBeanDefinition对象。

在解析<property>元素的value时,有对value属性,ref属性,idref属性及value标签下的各种子标签<ref>,<idref>,<bean>,<list>,<map>,<set>,<props>,<null>等进行处理,其中ref,idref属性及标签将返回RuntimeBeanReference对象,内部<bean>将递归地进行处理,并最终返回AbstractBeanDefinition对象,<list> <map><set><props>将对应地返回ManagedList, ManagedMap, ManagedSet, ManagedProperties对象并返回TypedStringValue对象,<null>标签将返回nullvalue属性或value字符串将返回TypedStringValue对象。

四、 所使用到的工具类

在此过程中所使用到的一些工具类和主要方法如下:

org.springframework.beans.BeanUtils:其内部的重载方法instantiateClass()将通过反射创建对象

org.springframework.util.CollectionUtils类:其提供了操作集合的一些有用的工具方法

org.springframework.util.ObjectUtils类:提供了操作对象的工具方法、主要包括判断数组是否为空、添加元素至数组中、给定类型的数组变为Object数组、null安全情况下的equals比较、null安全情况下对象,数组等变为字符串

org.springframework.util.SystemPropertyUtils类:用系统属性值替换字符串中的占位符参数

org.springframework.core.io.support. PropertiesLoaderUtils类:用于根据资源名或资源流加载java.util.Properties对象

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值