spring: xml到BeanDefinition的解析

XmlBeanDefinitionRead简称xmlRead ,其功能就是把xml文件转换为bean的描述类BeanDefinition。

  转换过程:

   1:找到对应的xml文件。

   2:转换为docment对象。

   3:docment对象翻译成BeanDefinition。

xmlRead的继承关系图

spring: xml到BeanDefinition的解析_第1张图片

Read的接口方法

spring: xml到BeanDefinition的解析_第2张图片

Read的实现类有:

所以xml配置bean只是spring其中的一种方法。

 

XmlRead的构造方法:

/**
 * Create new XmlBeanDefinitionReader for the given bean factory.
 * @param registry the BeanFactory to load bean definitions into,
 * in the form of a BeanDefinitionRegistry
 */
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
   super(registry);
}

需要传一个BeanDefinitionRegistry,spring中的实现类有

spring: xml到BeanDefinition的解析_第3张图片

DefaultListableBeanFactory是factory最基础的实现类,同时也是BeanDefinitionRegistry的实现类。

下面创建一个简单的spring工厂。

public static void main(String[] args) {
    // 一个简单的spring工厂
    //1.定位资源
    Resource resource = new ClassPathResource("app_1.xml");
    //2.工厂生成
    DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
    //3.创建Read
    BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
    //4.xml文件中的bean解析成beanDefinition
    beanDefinitionReader.loadBeanDefinitions(resource);
    //5.实例化单例的bean
    defaultListableBeanFactory.preInstantiateSingletons();
}

 

app_1.xml


    
    

load关键过程:

XmlBeanDefinitionReader:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
       。。。。。。。。
      //资源转为流
      InputStream inputStream = encodedResource.getResource().getInputStream();
      try {
         InputSource inputSource = new InputSource(inputStream);
         if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
         }
         return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
       。。。。。。。。。
 }
     
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {
   try {
      //xml解析为doc
      Document doc = doLoadDocument(inputSource, resource);
      return registerBeanDefinitions(doc, resource);
 }
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //创建一个docRead --->DefaultBeanDefinitionDocumentReader 由它来转换doc----》beandifition
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   int countBefore = getRegistry().getBeanDefinitionCount();
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   return getRegistry().getBeanDefinitionCount() - countBefore;
}
DefaultBeanDefinitionDocumentReader:
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   this.readerContext = readerContext;
   logger.debug("Loading bean definitions");
   Element root = doc.getDocumentElement();
   doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
   BeanDefinitionParserDelegate parent = this.delegate;
   this.delegate = createDelegate(getReaderContext(), root, parent);
    //判断命名空间是不是http://www.springframework.org/schema/beans  
   if (this.delegate.isDefaultNamespace(root)) {
      String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); //profile
      //处理 profile
      if (StringUtils.hasText(profileSpec)) {
         String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
               profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
         if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
            if (logger.isInfoEnabled()) {
               logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                     "] not matching: " + getReaderContext().getResource());
            }
            return;
         }
      }
   }
   preProcessXml(root);
   //解析doc
   parseBeanDefinitions(root, this.delegate);
   postProcessXml(root);
   this.delegate = parent;
}

      

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   //判断是不是http://www.springframework.org/schema/beans 
   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;
             //spring 原生的命名空间
            if (delegate.isDefaultNamespace(ele)) {
              //解析某个元素
               parseDefaultElement(ele, delegate);
            }
            //解析哪些自定义的标签 比如  context,mvc标签就是在这里处理的。
            else {
               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标签的处理
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      processBeanDefinition(ele, delegate);
   }
  beans的处理
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse
      doRegisterBeanDefinitions(ele);
   }
}

 

//关键步骤:doc的exelment  ----------》beandefinition

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(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));
   }
}
BeanDefinitionParserDelegate:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
  
   String id = ele.getAttribute(ID_ATTRIBUTE);
   String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

   List aliases = new ArrayList<>();
   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 (logger.isDebugEnabled()) {
         logger.debug("No XML 'id' specified - using '" + beanName +
               "' as bean name and " + aliases + " as aliases");
      }
   }

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

   AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
   if (beanDefinition != null) {
      if (!StringUtils.hasText(beanName)) {
         try {
            if (containingBean != null) {
                //id name 都配置,beanName 为id
               //如果id name 都不配置则自动生成:类似这种 com.spring.bean.BeanA#0,当然不一定就是这样,可以自己去研究一下。
               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);
      return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
   }

   return null;
}
public AbstractBeanDefinition parseBeanDefinitionElement(
      Element ele, String beanName, @Nullable BeanDefinition containingBean) {

   this.parseState.push(new BeanEntry(beanName));

   String className = null;
   if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
      className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
   }
   String parent = null;
   if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
      parent = ele.getAttribute(PARENT_ATTRIBUTE);
   }

   try {
      AbstractBeanDefinition bd = createBeanDefinition(className, parent);

      parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
      bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

      parseMetaElements(ele, bd);
      parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
      parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

      parseConstructorArgElements(ele, bd); 构造参数
      parsePropertyElements(ele, bd);  //property解析
      parseQualifierElements(ele, bd);   //Qualifier属性

      bd.setResource(this.readerContext.getResource());
      bd.setSource(extractSource(ele));

      return bd;
   }

到此为止 xml -----》doc-------------》 GenericBeanDefinition 的转换工作已近完成   这三和存储的内容都是一样的 只不过是不同的描述而已。Bean的生成,就是把GenericBeanDefinition 在转化成Bean。

 

 

 

 

 

你可能感兴趣的:(spring源码分析)